Flexで phpでいうsleepみたいなことをしてhttp requestを大量に発行する

イベント駆動のプログラミングがここまで違うとは思わなくて、
思わぬところではまったのでめも。

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が回数分だけアクセスされちゃうことになるので注意。

この生成の順番で超はまってしまった。。

最後

ながかった。。

Leave a Reply