views:

93

answers:

3

Sequential Asynchronous calls are gross. Is there a more readable solution?

The problem is this is hard to follow:

ajaxOne(function() {
  // do something
  ajaxTwo(function() {
    // do something
    ajaxThree()
  });
});

where the anonymous functions are callbacks that are called on server response.

I'm using a third party API to make the AJAX calls, so I need a generic solution.

+1  A: 

If you have only one nested function, it's Ok to leave it as is, but if you have several nested calls, you should consider writing these callbacks in a separate method, and calling it from the nested function...

ajaxOne(function(result) { handleAjaxOneCallback(result, someExtraNeededArg); } );

function handleAjaxOneCallback(result, someExtraNeededParam) {
  // do something

  ajaxTwo(function(result) { handleAjaxTwoCallback(result, myFoo, myBar); });
}

function handleAjaxTwoCallback(result, foo, bar) {
  // do something

  ajaxThree(/* ... */);
}
Pablo Cabrera
A: 

If you don't need the closure scope in your callbacks, which you probably won't, you can just put the callbacks into separate functions and call them by their name. like:

var ajaxOne = function() {
    doTheAjax(callbackOne);
}
var callbackOne = function() {
    //funny things ...
    doTheAjax(callbackTwo);
}
var callbackTwo = function() {
    //even more funny things ...
}
Techpriester
My question was probably poorly formed. This is actually the method I use as the line would get way too big in my example. However the logic is hard to follow because the calls must still be traced.
Fletcher Moore
+2  A: 

functional programming to the rescue! jsdeferred lets you write your example like so:

next(ajaxOne).next(ajaxTwo).next(ajaxThree).error(function(e){alert('An error happened:' + e)})

each of the "sequential" ajaxOne/Two/Three functions receives the returned result of its predecessor as parameter. If you need to pass in additional parameters, you can expose them in a global object before you invoke your ajax chain.

Franz
Although that approach take significantly more effort to do, it sure is very nice and clean :) But it's not really a matter of "functional programming".
Techpriester
This looks really cool, but I cannot figure out how the deferred class works internally.
Fletcher Moore
A look at jsdeferred's source (http://github.com/cho45/jsdeferred/blob/master/jsdeferred.js) tells you that the next-function simply waits for the first ajax call to arrive (using setTimeout) and then sends the next.
Franz