Chaining Ajax Calls Using Deferred Objects In jQuery

jQuery 1.5 introduced deferred objects. From the jQuery site:

jQuery.Deferred(), introduced in version 1.5, is a chainable utility object that can register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function.

I learned about deferred objects recently when I needed to chain two ajax calls together. Using deferred objects made chaining them together relatively simple. Here’s some example code:

$.when($.get("http://example.com/page1"), $.get("http://example.com/page2"))
 .done(function(successArgs1, successArgs2) {
    console.log(page1Args[0]);
    console.log(page2Args[0]);
 })
 .fail(function(jqXHR, textStatus){
    console.log("Error loading " + this.url);
    console.log("Status: " + jqXHR.status + " " + jqXHR.statusText);
  });

jQuery’s ajax functions return a deferred object that can be passed to jQuery.when. jQuery.when accepts any number of deferred objects, and allows you to assign callbacks that will be invoked when all of the deferred objects have completed.

The arguments to the .done function that is chained onto .when are success handler functions that are put into a callback queue. In my example I just pass one function, but you can actually pass any number of them. The function will be invoked when *both* .get calls complete successfully. It will be passed an array for each of the calls to .get that contain the arguments that .get would normally pass to it’s ‘success’ function.

Since jQuery.get’s success function normally passes ‘data, textStatus, and jqXHR’ arguments to it’s success handler, that is what will be in the array passed to the handler function. In this example I just log the data to the console. Not very useful, but good enough for our purposes.

The arguments to the .fail method are error handler functions that are put into a callback queue. The functions will be invoked in the same order as they were put into the queue. The functions will only be called once though even if more than one of the ajax calls passed to .when fail. In our example, the error handler function will be passed the same arguments that .get would normally pass to it’s failure handler. .get normally passes jqXHR, and textStatus arguments, so that is what will be passed to the handler. In my example, I just log an error message to the console.

Using deferred objects this way simplifies the code we have to write in order to handle chained ajax calls. Instead of several levels of ajax calls nested within previous ajax success functions, we can write relatively clear, concise code that is easier to understand and easier to maintain.