简体   繁体   中英

Will calling async functions within different functions still cause async behavior?

Let's say I have multiple functions func1 , func2 , func3 , etc.....

And they all contain an AJAX/async function within them:

function funcX(){ // some ajax request }

If in a main function I am calling func1 , func2 , func3 sequentially like so:

$(document).ready(function(){ 

      func1();
      func2();
      func3();
      ...
}

Will each ajax/async function's call be certain to execute in the order of their parent functions? At first I thought they might be, but the behavior of my program seems to be suggesting otherwise...

If not, is there a good (hopefully simple?) alternative to having a long chain of callbacks?

Will each ajax/async function's call be certain to execute in the order of their parent functions?

They should execute in order, but their internal callbacks can be called in any order.

If not, is there a good (hopefully simple?) alternative to having a long chain of callbacks?

You could use a promise , and execute the next function when the promise has been resolved.

This example uses jQuery...

var fn1 = function () {
    var d = $.Deferred();
    setTimeout(function () {
        $("body").text("Callback 1 done.") && d.resolve();
    }, Math.random() * 1300 + 800);
    return d.promise();
};

var fn2 = function () {
    var d = $.Deferred();
    setTimeout(function () {
        $("body").text("Callback 2 done.") && d.resolve();
    }, 500);
    return d.promise();
};

$.when(fn1(), fn2()).then(function () {
    setTimeout(function () {
        $("body").text("All done.");
    }, 300);
});

jsFiddle .

We use $.when() and pass the invoked functions we want to execute to it. We then use then() to show a final message (I placed a setTimeout() here so you can see the last resolved function's message in the document).

Each of these functions have their own deferred object which return the promise. A setTimeout() mocks an XHR for example's sake. When this callback is executed, we resolve the deferred object.

Once both have been deferred, we reach the callback for then() .

To serialize tasks, I've written a helper function, which can also be found in my earlier answer :

function serializeTasks(arr, fn, done)
{
    var current = 0;

    fn(function iterate() {
        if (++current < arr.length) {
            fn(iterate, arr[current]);
        } else {
            done();
        }
    }, arr[current]);
}

It takes an array of values (in your case those are actually functions), a loop function and a completion handler. Below is the loop function:

function loopFn(nextTask, fn) 
{
    fn(nextTask);
}

It accepts an intermediate completion function as the first argument and each element of the aforementioned array.

To set everything in motion:

serializeTasks([func1, func2, func3], loopFn, function() {
    console.log('all done');
});

Your functions are called with a single argument which should be passed to the AJAX success callback, eg

func1(nextTask)
{
    $.ajax({
        ...,
        success: nextTask
    });
}

The order in which the asynch results are returned is not deterministic, and may wary every time.

func2 might complete before func1 etc

It is important to ensure correct order of execution. One pattern is to call the next function in the success callback of the prior function

Ex:

$.get("/someUrl",function(){
   $.get("/nextAjaxCall", function(){

   .....
   });
});

If the dependency chain is very simple, I don't think it's necessary to introduce a framework to handle this

Or look at async library and it's awesomeness !

async

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