2

別の関数から複数回呼び出された非同期関数が最後の反復からの呼び出しを終了したときを判断する方法が少し混乱しています。

function MainAsyncFunction(callback) {
  for (var i = 0; i < 10; i++) {
    SubAsyncFunction(function(success) {
      if (i >= 10 && success) { // THIS IS WRONG?!
        callback(true); // happens too early
      }
    });
  }
};

function SubAsyncFunction(callback) {
  SubSubAsyncFunction(function() {
        callback(true);
  });
}

私がやっていることは、25の宛先に制限されているGoogle Distance Matrixサービスを呼び出すことです。したがって、このサービスを複数回呼び出すには、宛先の配列を分割する必要がありますが、いつ終了するかわかりません。

コードのメインビットでは、MainAsyncFunctionのループの2回目の反復が、コールバックを実行したときにまだ完了していないことがわかります。

私の問題は、JavaScriptで非同期関数を処理するときにイベントの順序に頭を悩ませていないことだと思います...主題が通常どのように達成されるかを説明してください。

4

3 に答える 3

7

非同期操作のステータスを表すトークンとして機能するjQueryDeferredオブジェクトを使用できます。

以下は単純化された例です。

//set up your sub method so that it returns a Deferred object
function doSomethingAsync() {
    var token = $.Deferred();
    myAsyncMethodThatTakesACallback(function() {
        //resolve the token once the async operation is complete
        token.resolve();
    });
    return token.promise();
};

//then keep a record of the tokens from the main function
function doSomethingAfterAllSubTasks() {
    var tokens = [];
    for (var i=0; i < 100; i++) {
        //store all the returned tokens
        tokens.push(doSomethingAsync());
    }

    $.when.apply($,tokens)
        .then(function() {
            //once ALL the sub operations are completed, this callback will be invoked
            alert("all async calls completed");
        });
};

以下は、OPの更新されたコードの更新されたバージョンです。

function MainAsyncFunction(callback) {
  var subFunctionTokens = [];
  for (var i = 0; i < 10; i++) {
    subFunctionTokens.push(SubAsyncFunction());
  }

  $.when.apply($,subFunctionTokens)
  .then(function() {
    callback(true);
  });
};

function SubAsyncFunction() {
  var token = $.Deferred();
  SubSubAsyncFunction(function() {
        token.resolve();
  });
  return token.promise();
};​
于 2012-03-29T13:51:38.877 に答える
0

問題は、の値がiループ内で絶えず変化し、条件付きでループに失敗した後、最終的に範囲外になることです。

これを修正する最も簡単な方法は次のとおりです。

for( i=0; i<5; i++) { // or whatever your loop is
    (function(i) {
        // the value of i is now "anchored" in this block.
    })(i);
}
于 2012-03-29T14:08:42.150 に答える
0

おそらくajaxStop()イベント?これは、すべてのアクティブなAJAXリクエストが完了したときにのみ発生するjQueryイベントです。

于 2012-03-29T13:49:47.767 に答える