イベント駆動のプログラミングがここまで違うとは思わなくて、
思わぬところではまったのでめも。
PHPならこう書きたい・・
ハマったのは、phpで言うところの
foreach ($myRssUrlList as $key=>$url) {
$html[] = file_get_contents($url);
}
みたいなことがしたかったんですが、
イベント駆動の考え方でこれがめんどくさくって。
Flex的には file_get_contents にイベントを設定して、
file_get_contentsが完了したら次にやる
っていう感じに書き方をするわけで、
そのまま書くとこうなっちゃう。
<mx:HTTPService id="httpService" />
function httpReq():void {
for each (var url:String in myRssUrlList) {
httpService.url = url;
httpService.addEventListener(ResultEvent.RESULT,function():void{});
httpService.send();
}
}
(myRssUrlListにはRSSのURLが10個くらい入ってるイメージ)
が、 これだとうまくいかない。
どうなるかというと、 例えばmyRssUrlListにURLが10個入ってると、
最後のURLの結果が10回取得されて終わっちゃう。(自分の環境では)
ほぼ同時に(一応順番どおりだけど)リクエストを全部走らせて、
終わったものから順にfuntionを走らせるので、
1個のオブジェクトの結果をひたすら上書きしていて、
イベントのfunctionが走るタイミングでは、指定したURLの結果かどうかが担保されていないから。
さらに全部ほぼ同時にrequestが走るので、10とかならまだしも10000とかURLリストがあると
即効落ちるw
でしょうがないので、毎回オブジェクトを作ることにする。
function httpReq():void {
for each (var url:String in myRssUrlList) {
var httpService:HTTPService = new HTTPService();
httpService.url = url;
httpService.addEventListener(ResultEvent.RESULT,function():void{});
httpService.send();
}
}
こうすると毎回別のオブジェクトなので、うまく取れるようになるわけだけど、
やっぱり問題は全部同時に走らせちゃうこと。
で、次に思ったのが、
foreach ($myRssUrlList as $key=>$url) {
$html[] = file_get_contents($url);
sleep(3);
}
こう書きたい。
ので、 flexでsleepを探してみる。
javascriptでも似たようなことで詰まった覚えがあるので、
あんまり期待しない。
Flex で Sleep的な~
で、 やっぱ sleepみたいなことはなかったけど、(探したりないだけかもしれないけど)
変わりに Timer();を使うといいとか書いてあったので、それを使ってみる。
//HTTPリクエストのタイマー
private function httpQue():void {
var timer:Timer = new Timer(2000,myRssUrlList.length); //2秒ごとにイベント発動
for each (var url:String in myRssUrlList) { //とにかくmyRssUrlListの数だけtimerイベントを発動させる
timer.addEventListener(TimerEvent.TIMER,httpReq);
}
timer.start();
}
//HTTPリクエストを発行するメソッド
private function httpReq(evt:Event):void {
var url:String = myRssUrlList.shift() as String;
var httpService:HTTPService = new HTTPService();
httpService.url = url;
httpService.addEventListener(ResultEvent.RESULT,function():void{});
httpService.send();
}
これで2秒置きにHTTPリクエストが発行できるようになる。
とりあえず10000くらいは処理できたので、
あとはPCがんばれ!
ちなみに
タイマーのところで
これを timer.addEventListener(TimerEvent.TIMER,httpReq);
こうかいちゃうと
timer.addEventListener(TimerEvent.TIMER,function(evt:TimerEvent):void{httpReq(url);});
functionの生成の順番のせいで、最後のURLが回数分だけアクセスされちゃうことになるので注意。
この生成の順番で超はまってしまった。。
最後
ながかった。。