1

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?

2
  • possible duplicate of How to synch JavaScript callbacks? Commented Jul 3, 2013 at 1:42
  • Does it have to execute in order? Commented Jul 3, 2013 at 1:44

4 Answers 4

3

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().

Sign up to request clarification or add additional context in comments.

10 Comments

So, for example, the ajax function in func3 could complete first before the one in func1 ?
If each of the functions (func1, func2, and func3 from your example) all include some ajax call or other async operation, there is no way to know for sure which one will return or complete first. With Promises, you have more control over the order in which they start, which ensures that they happen in the "right" order. You could do this with callbacks, but the code may be harder to read at the end of the day.
@Gnuey the functions will complete in any order, but you get two choices with this method, the first ( when each ajax call depends on the previous) you call the next function when the previous is complete, the second is when you want to increase performance (and there is no dependency between the ajax calls), let them run together and don't handle the calls, but use the returned promises to control what you want to do with the data after. correct me if I'm mistaken.
@alex I still wonder why you didn't go with the callback functions solving this since they are already functions ! e.g. function(args .. , callbackFn ){} ..
Thanks for your answer. I'm guessing there is no true point to the math random?
|
1

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, e.g.

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

2 Comments

wow, that's pretty cool. Reminds me of linked lists in c++. Will give it a try but it may take me some time.
@Gnuey Take all the time you need :)
0

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

Comments

0

Or look at async library and it's awesomeness !

async

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.