简体   繁体   中英

jQuery JavaScript Nested Asynchronous Functions callback

I'm a little confused how to determine when async function called multiple times from another one is finished a call from the last iteration:

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

What I'm doing is calling the Google Distance Matrix service , which has a limitation of 25 destinations, hence I'm having to split my array of destinations to call this service multiple times but I don't understand when it's finished.

and in the main bit of code I can tell that the second iteration of the loop in the MainAsyncFunction hasn't yet completed when it does a call back.

I think my problem is I haven't got my head around the order of events when dealing with Async functions in JavaScript... please explain how the subject is normally achieved.

You could use the jQuery Deferred object, which acts as a token representing the status of an async operation.

The following is a simplified example:

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

The following is an updated version of the OP's updated code:

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

Perhaps the ajaxStop() event ? This is a jQuery event that only fires when all active AJAX requests are completed.

The problem is that the value of i is constantly changing in the loop, finally being out of bounds after failing the loop conditional.

The easiest way to fix this is:

for( i=0; i<5; i++) { // or whatever your loop is
    (function(i) {
        // the value of i is now "anchored" in this block.
    })(i);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM