Using jQuery $.deferred with multiple ajax calls

I've been working on SPA (single-page application) with different frameworks, such as AngularJS and DurandalJS. Most of the time, each partial or viewModel needs multiple restful APIs/Endpoints to render the full UI. Writing nested ajax calls is ugly, painful to debug and most importantly slow. Here I am going to show you an elegant and efficient way to handle multiple ajax calls with jQuery Deferred.

In the following example, I am making 3 ajax calls in a single function. Here is the ugly, painful, slow way to do it.

function getLocation() {
    $.get("http://ipinfo.io", function (response1) {
        if (response1) {
            $.get("http://ipinfo.io", function (response2) {
                if (response2) {
                    $.get("http://ipinfo.io", function (response3) {
                        if (response3) {
                            // handle the rest
                        }
                    }, 'jsonp');
                }
            }, 'jsonp');
        }
    }, 'jsonp');
}

I'm sure you've done this before. At least I've done it. Because it works. But it's so slow:

ajaxCall1 -> wait to be done ->

ajaxCall2 -> wait to be done ->

ajaxCall3 -> wait to be done -> go

If we could do this: All three requests in parallel:

wait for all three ajaxCalls to be done -> go

It would be much faster. With jQuery $.deferred object, you can not only make multiple ajax calls efficiently, but also make it chainable. Here you go:

var deferred = $.Deferred();

function getLocation() {

    var ajaxCall1 = $.get("http://ipinfo.io", {}, null, 'jsonp');
    var ajaxCall2 = $.get("http://ipinfo.io", {}, null, 'jsonp');
    var ajaxCall3 = $.get("http://ipinfo.io", {}, null, 'jsonp');

    $.when(ajaxCall1, ajaxCall2, ajaxCall3)
     .done(function (response1, response2, response3) {
        if (response1[0].country === 'US') {
            deferred.resolve();
        } else {
            deferred.reject(response1[0], response2[0], response3[0]);
        }
    });

    return deferred.promise();
}

getLocation()
.then(
    function () {
        alert('You are in US');
    }, 
    function (response1, response2, response3) {
        alert('You are in ' + response1.city
                     + ', ' + response2.region
                     + ', ' + response3.country);
    }
);

Demo

Yang Zhao

Read more posts by this author.


Comment