Обратный вызов вложенных асинхронных функций jQuery JavaScript - PullRequest
2 голосов
/ 29 марта 2012

Я немного запутался, как определить, когда асинхронная функция, вызванная несколько раз из другой, завершает вызов из последней итерации:

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);
  });
}

То, что я делаю, - это вызов службы Google Distance Matrix , который имеет ограничение в 25 пунктов назначения, поэтому мне приходится разбивать мой массив пунктов назначения, чтобы вызывать эту службу несколько раз, но я не не понимаю, когда это закончится.

и в основном бите кода я могу сказать, что вторая итерация цикла в MainAsyncFunction еще не завершилась при обратном вызове.

Я думаю, что моя проблема в том, что я не разбираюсь в порядке событий при работе с асинхронными функциями в JavaScript ... пожалуйста, объясните, как обычно достигается предмет.

Ответы [ 3 ]

7 голосов
/ 29 марта 2012

Вы можете использовать объект jQuery Deferred , который действует как токен, представляющий состояние асинхронной операции.

Ниже приведен упрощенный пример:

//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");
        });
};

Ниже приведена обновленная версия обновленного кода ОП:

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();
};​
0 голосов
/ 29 марта 2012

Проблема в том, что значение 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);
}
0 голосов
/ 29 марта 2012

Возможно, событие ajaxStop () ?Это событие jQuery, которое вызывается только после завершения всех активных запросов AJAX.

...