鈍足ランナーのIT日記

走るのが好きな5流のITエンジニアのブログ。

趣味の範囲は広いけど、どれも中途半端なクソブロガー楽しめるWebアプリを作ってあっと言わせたい。サーバーサイドPerl(Mojolicious)、クライアントサイドVue.js。Arduinoにも触手を伸ばす予定。

JQuery Defferedで直列処理。直列数は可変。引数も変えたい

GoogleMaposElevationのAPIにアクセスするとき、
APIを並列で投げてみたんですが、使用制限に引っかかってしまった。
高負荷をかけるような使い方は制限されているようだ。

さて、非同期API直列にすれば、使用制限を回避できると思われた。
要件的には、直列数は可変。引数も可変と感じになる。

なかなかそういうサンプルソースにはありつけなかったので
自分で調べ試行錯誤し、解決してみた。(突っ込みどころ満載と思うが・・・)


これだと3直列15秒で処理が終了する

  function hoge(arg){
    var defer = $.Deferred();
    setTimeout(function() {
      console.log(arg);
      defer.resolve();
    }, 5000);
    return defer.promise();
  }

  console.log("start");
  hoge(1).then(function(){return hoge.call(null,2)}).then(function(){return hoge.call(null,3)});

自分がやりたいのは、1直列だったり、2直列だったり可変にして、さらに
それぞれ引数を変えたい。

引数ないバージョンは上記を参照してできた。

function hoge(){
  var defer = $.Deferred();
  setTimeout(function() {
    console.log("hoge");
    defer.resolve();
  }, 5000);
  return defer.promise();
}

var tasks = [hoge, hoge, hoge];

tasks.reduceRight(function (x, y) {
  return function () {
    return y().done(x);
  };
})();

引数ありバージョンはいったいどうやるのだろう・・
関数を登録(push)したときの引数が、実行するときに
保存されていなくてhoge10となってしまう。
はたしてどうすればいいのだろうか。

function hoge(arg){
  var defer = $.Deferred();
  setTimeout(function() {
    console.log("hoge" + arg);
    if (arg < 5){
      defer.resolve();
    }
    else{
      defer.reject("failed!");
    }
  }, 2000);
  return defer.promise();
}

var tasks = [];
for (var i=0;i<10;i++){
  tasks.push(function(){return hoge.call(null,i)});
}

tasks.reduceRight(function (x, y) {
  return function () {
    return y().done(x).fail(function(result){console.log(result)});
  };
})();

console.log("start");

クロージャを思い出した。
[JavaScript] 猿でもわかるクロージャ超入門 まとめ - DQNEO起業日記
こんな感じに書いたら想定した動作になったのであった。
終わり。

function hoge(a){
  var arg = a;
  return function(){
    var defer = $.Deferred();
    setTimeout(function() {
      console.log("hoge" + arg);
      if (arg < 5){
        defer.resolve();
      }
      else{
        defer.reject("failed!");
      }
    }, 2000);
    return defer.promise();
  }
}

var tasks = [];

for (var i=0;i<10;i++){
  tasks.push(hoge.call(null,i));
}

tasks.reduceRight(function (x, y) {
  return function () {
    return y().done(x).fail(function(result){console.log(result)});
  };
})();

console.log("start");