Working with jQuery’s AJAX, Promises and Deferred objects

jQuery’s implementation of making AJAX calls is quite easy to understand. There is $.ajax(), $.get(), $getJSON(), $.post() – which are all xhr requests, just different ways of writing it. It probably has the most straightforward syntax available and that’s why developers continue to use it, more than other libraries.

The funny thing is, once we get to know it, we almost want to do everything via AJAX. From fetching and posting data to grabbing static files and compiling templates, – you name it. Before you know it, we’re making AJAX calls all over the place. It can get ugly really fast. Without knowing Promises and Deferred, our code syntax will get messy.

For instance, you’ve probably run into this problem at one point.

Notice our “results” array is empty after we run our function:

The issue here is our getData() method continues to run even before our AJAX call finishes. So naturally, our results will log empty. One thing we DON’T want to do is to continue our logic inside the $.get() utility!

Enter Promises

jQuery have promises implemented with their AJAX methods. In a nutshell, they are utilities that allow us to work with events that have completed or put them in queues or chain them – all of that good stuff.  In our case, we need a “promise“. This allows us to interact with our AJAX requests – well outside our $.get() utility. So we can continue with our logic as designed.

So let’s solve our issue with .done() – which is a method that comes with $.get():

As you can see, we can use our function getData() – anywhere in our code as we’ve intended it to be. Note that there is also .fail(), .always()  – which are the other methods for our $.get() promise object. .fail() for – when our call fails, .always() occurs every time it runs. The syntax is very self-explanatory.

Now we can also do this:

Which may server as a global error handler for our getData() function.

You can also do both!

So our method getData() – will always run our success function inside $.get(), while we use .done() – everywhere else in our code.

Multiple AJAX calls

What about multiple (different) AJAX calls? Something like below:

This is fine, but it looks rather clumsy don’t you think. There is a method called .when() – which deals with stuff like this.

Instead of writing multiple .done(), we can elegantly compile them into a single block. We still get access to the same objects – as if we’re dealing with each AJAX call individually.

Note that each response returns an array. So for example you want to access the data of the first response, you do a r1[0] and so forth.

Multiple Dynamic AJAX calls

Now this one is tricky. It has been asked in StackOverflow – which has an answer I would have not guessed. First thing is to get our requests in an array format. So this will be the dynamic part and it’s up to you how you want to design that. Now, $.when is smart enough to process the calls – if you pass them in single or an array.

But note that we use .apply after $.when This is so we can have access to a special variable called “arguments”. The arguments hold the responses from our array of calls, in a multi-dimensional array format.

As you can see, our promise is still in-tact and does it’s thing for dynamic AJAX calls.

$.Deferred()

As the method implies, $.Deferred() is to put in on hold, until you’re ready to interact with it. $.Deferred() is useful when we have actions such as multiple AJAX calls and we want to continue interacting with them at a later time.

Building on our example, let’s wrap our $.when() inside a function so we can call it later. Let’s use the .resolve() function of $.Deferred to illustrate:

You see that we are delaying our .resolve by 2 seconds using setTimeout(). You will see our def.promise() will take 2 seconds to return.

Also, now we have an accessible defCalls() promise object that we can use at a later time:

You can also pass parameters to .resolve() – for later use in our defCalls() promise object. For example, the responses that came back from our call:

What about multiple dynamic calls? We already learned about .apply(). We simply do the same thing so we can pass “arguments”:

Lastly, let’s just say we want to create an action for failed events, we use the .reject() method for that:

As you can see, there many benefits in using promises and deferred objects – especially in asynchronous programming with jQuery’s AJAX. Not only that it will make your code easier to read. But it also makes it easier to debug, well factored and organized – the way jQuery intended it to be.

I would like to read comments on how you’re using these objects in your own code. Please leave them below.

6 Comments

  1. thank you good tutorial, very well explained with code snippets.
    I request you to write more live example for this, by using webservice,twitter,or any

    Reply
  2. Hi Michael,
    I think instead of writing this:

    function defCalls(){
    var def = $.Deferred();
    var requests = [
    getData1(),
    getData2()
    ]
    $.when.apply($,requests).done(function(){
    def.resolve(arguments);
    })
    return def.promise();
    }

    defCalls().done(function(arr){
    //now we have access to array of data
    console.log(arr);
    })
    you can simmply return the $when.apply() like so:
    function defCalls(){
    var requests = [
    getData1(),
    getData2()
    ];
    return $.when.apply($,requests);
    }

    defCalls().done(function(){
    //now we have access to array of data
    console.log(arguments);
    })

    Reply

Leave a Comment.