3

Didn't know how else to put this.

Say I have a JavaScript method that makes some AJAX calls:

function makeAJAXCalls()
{
    // who knows how long this will take
}

And I don't want the next function to execute until all the AJAX calls are complete. I also don't want to put the next function call into the success callback for the AJAX call.

Is there a way I can like chain these, so the next function doesn't get called until makeAJAXCalls() is done everything it needs to do?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
slandau
  • 23,528
  • 42
  • 122
  • 184

6 Answers6

3

You could use jQuery's $.when() functionality.

$.when(makeAjaxCalls()).done(function () { 
   // Do other things here 
});

You can even add multiple functions to the when if you wanted all of those to be completed first. These are all called Deferred Objects.

Mike Fielden
  • 10,055
  • 14
  • 59
  • 99
  • This is very interesting. Does it call as soon as I make that bind or is it binded to the AJAX function and only gets called when the AJAX function is called? – slandau May 19 '11 at 20:14
  • The done part will only fire once the function is completely finished. – Mike Fielden May 19 '11 at 20:14
  • This will only work if `makeAjaxCalls` returns deferred objects. – Matt Ball May 19 '11 at 20:16
  • @mike but if the makeAjaxCalls fires the ajax requests, does done wait until all responses are completed, or does it just fire when the makeAjaxCalls method exits? Those are two very different things.... – hvgotcodes May 19 '11 at 20:16
  • @Matt very true... I am assuming that it does :) @hvgotcodes Good question, I will test it – Mike Fielden May 19 '11 at 20:19
  • That's really not a safe assumption, given the OP's apparent lack of awareness of deferred objects. – Matt Ball May 19 '11 at 20:19
  • For general reference... http://stackoverflow.com/questions/4866721/what-are-deferred-objects – Mike Fielden May 19 '11 at 20:21
2
var queueCount =0;
function makeAjaxCalls()
{
    queueCount+=7; // or however many calls you need to make.
    // make your ajax calls. onSuccess (or failure), call checkQueue();
}
function checkQueue()
{
    queueCount--;
    if (queueCount <=0)
    {
       doNext();
    }
}

This leaves the calls asynchronous, which may be the intent here.

John Green
  • 13,241
  • 3
  • 29
  • 51
  • Thanks. We would consider this a classic approach. Although I love jquery, sometimes it is just easier to solve the problem through simple means. – John Green May 19 '11 at 20:19
1

You are really limiting your options. AJAX is asynchronous by nature (unless you use synchronized xhrs, which you don't want because they freeze the browser). So your only option is to handle it in the callback, because the callbacks are the only way you know the request has completed, and where the data from the requests gets passed when they complete.

Because you have multiple callbacks, and you want to wait till they are all done, you can put the same function call in all the callbacks, and that function can track which responses have come back, and only proceed if all responses are there.

so you can do something like

var resultsHolder = [];
var syncer = function(response){
    // add results to resultsHolder on call

    if (resultsHolder.lengh === numberExpected) {
     //proceed
    }
}

then use syncer in your makeAllRequests method

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
1

You could, by making your calls synchronous.

Example: Synchronous request

Although you might want to take note that this will probably cause an undesired blocking effect on the rest of your application that might call into question the reason for using synchronous xhr.

Quintin Robinson
  • 81,193
  • 14
  • 123
  • 132
1

You can make chained ajax calls if you're using jQuery 1.5+. This works because $.ajax() returns a jqXHR which is also a Deferred Object.

function makeAjaxCalls()
{
    return $.ajax(/* snip options */);
}

function handleSuccess(data)
{
    // do something with the data
}

function nextAjax()
{
    return $.ajax(/* snip other options */);
}

// then...
makeAjaxCalls().success(handleSuccess).complete(nextAjax);
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
0

You should take your own callback as a parameter to the function.
This way, the caller can decide what to do next.

You could also return a Deferred object.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964