25389


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

[code]

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

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

[code]

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

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

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

* * *

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

[code]

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

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

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

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

* * *

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


CC BY-SA 3.0
2016-06-01T14:25:21.060
25362
2016-06-03T10:42:52.827
2016-06-03T10:19:04.100
7966
7966
question
javascript jquery ajax
jQueryでイベントの処理結果を待つようなループを書きたい


jQueryは直接関係ありませんが、Promiseを使った例を二つほど。

## Promiseをつないでいくパターン

[code]

    var requestTable = ["owner","users","lines","info"];
    var promise = new Promise(function(res, rej) { res("init"); });
    requestTable.forEach(function(val) {
      promise = promise.then(function(prevData) {
        return new Promise(function(res, rej) {
          $.get("foo.html",null,function() {
            console.log(val + ": prev is " + prevData + ".");
            res(val);
          });
        });
      })
    });
    promise.then(function(lastData) {
      console.log("all done. last data is: " + lastData);
    });
    
[/code]

## Promise.all

[code]

    var requestTable = ["owner","users","lines","info"];
    var promiseAll = [];
    requestTable.forEach(function(val) {
      promiseAll.push(new Promise(function(res, rej) {
        $.get("foo.html",null,function() {
          console.log(val + " done.");
          res(val);
        });
      }));
    });
    Promise.all(promiseAll).then(function(dataList) {
      dataList.forEach(function(data) {
        console.log("result data: " + data);
      });
    });
    
[/code]

> callback処理の完了を待ってから次ループに移り

という動作をするわけではないですが、目的は果たせるのではないでしょうか。


CC BY-SA 3.0
2016-06-02T01:42:03.497
25371
2016-06-02T01:42:03.497
15537
25362
answer


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

[code]

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

[code]

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

このような非同期処理のチェーンに関してはazuさんの書かれた[JavaScript
Promiseの本](http://azu.github.io/promises-book/)が非常に参考になると思いますのでぜひご一読ください。


CC BY-SA 3.0
2016-06-02T11:16:46.477
25389
2016-06-03T10:42:52.827
2016-06-03T10:42:52.827
8532
8532
25362
answer