jQueryでイベントの処理結果を待つようなループを書きたい

投稿者: Anonymous

以下のような配列があり、これをループで処理します。

var requestTable = ["owner","users","lines","info"];
$.each(requestTable, function(i, val){
    // ループ処理
});

その際に、requestTableのループではそれぞれサーバーからGETでデータを取得します。

// ループ処理の中身
$.get("./url...?type="+val, {}, function(data){
    // ここの処理完了を待って次のループに移りたい
});

ループ1回ごとに、$.get()を呼び出したいのですが、callback処理の完了を待ってから次ループに移りたいのです。というのも、$.get()の結果を必要としているためです。

これを綺麗なコードで書きたいのですが、どうしたら良いでしょうか?


追記です。
$.Deferredを使う必要があるという事は分かります。

var df = $.Deferred();
//処理
df.resolve();
df.done(function(){
    //処理が終了した時に行う事
});

df.done()の中で行うべきところを、次のループ、次のループという具合に繰り返したいという事です。

メソッドチェインにしても良いのかもしれませんが、はじめの配列にある文字列を繰り返し処理したいだけなので、同一処理を繰り返して書きたくありません。

web系の日が浅いため、頭がこんがらがってうまくコード化できません。
申し訳ありませんが、御教示ください。


再追記です
実行順序を守り、ループごとの実行の終了を待たなければならないのには理由があります。
質問の趣旨に直接関係ないと思い、説明を省いていたのですがループn 回目の結果を使ってループn+1 回目の$.get()(実際には$.ajax())のURLパラメータとしたかったのです。
web APIをajaxでたたき、取得したGETデータをもとに次のループでURLを作成して再びweb APIを実行するという再帰処理が必要となっています。
説明不足となってしまって申し訳ありません。

解決

繰り返しの回数が決まっているのであれば、PromiseとArray.prototype.reduceを組み合わせるのがシンプルです。実装の際はasyncFuncをajax処理に置き換えてください。

_x000D_

_x000D_

var requestTable = ["owner","users","lines","info"];_x000D_
_x000D_
function asyncFunc(api, param){_x000D_
  var d = $.Deferred();_x000D_
  console.log(api + ' called with ' + param);_x000D_
  setTimeout(function(){_x000D_
    console.log(api + ' end');_x000D_
    d.resolve("return value of " + api);_x000D_
  }, Math.random()*2000);_x000D_
  return d.promise();_x000D_
}_x000D_
_x000D_
requestTable.reduce(function(promise, api){_x000D_
  return promise.then(function(param){_x000D_
    return asyncFunc(api, param);_x000D_
  });_x000D_
}, $.Deferred().resolve('initial value')).then(function(){_x000D_
  console.log("complete!");_x000D_
});

_x000D_

<script src="https://code.jquery.com/jquery-2.2.4.js"></script>

_x000D_

_x000D_

_x000D_

このような非同期処理のチェーンに関してはazuさんの書かれたJavaScript Promiseの本が非常に参考になると思いますのでぜひご一読ください。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *