イベント駆動のプログラミングがここまで違うとは思わなくて、
思わぬところではまったのでめも。
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が回数分だけアクセスされちゃうことになるので注意。
この生成の順番で超はまってしまった。。
最後
ながかった。。