May 19, 2011

A Robust Way To Handle Asynchronous Requests Using jQuery 1.5+

jQuery 1.5 includes a number of improvements in Ajax/asynchronous events and introduces new Deferred callback management system. It provides flexible ways to provide multiple callbacks. Let us take an example to understand deferred punch. The objective of example is to call two Asynchronous methods (asyncMethod1,asyncMethod2) and other method(finalMethod) when both asynchronous methods are executed.

Approach 1:


function asyncMethod1(){
    return $.get('/request1.htm', asyncMethod2);
}

function asyncMethod2(){
    return $.get('/request2.htm', finalMethod);
}

function finalMethod(){
alert( 'BOTH ajax requests have completed!' );
}

asyncMethod1();

In this approach, asyncMethod2 is called on success of asyncMethod1 request and finalMethod is called as callback method of asyncMethod2 means both async methods are not concurrent, but called sequentially. so our object is defeated.

Approach 2:


var completedRequests = 0;

function asyncMethod1(){
    return $.get('/request1.html', processResults);
}

function asyncMethod2(){
    return $.get('/request2.html', processResults);
}
function processResults(){
    completedRequests += 1;   
    if (completedRequests >= 2){
    completedRequests  = 0;
    finalMethod();
    }
}

function finalMethod(){
alert( 'BOTH ajax requests have completed!' );
}

asyncMethod1();
asyncMethod2();

In above approach, A variable is used to count number of executed request. processResults is callback functions of both asyncMethod1 and asyncMethod2. When both requests are completed then finalMethod is called. It's not perfect approach but alternate solution.

Approach 3:(New Way)

Concurrent Ajax requests are easily accomplished with $.when.


function asyncMethod1(){
    return $.get('/request1.html');
}

function asyncMethod2(){
    return $.get('/request2.html');
}

function finalMethod(){
alert( 'I fire once BOTH ajax requests have completed!' );
}

$.when( asyncMethod1(), asyncMethod2())
    .then(finalMethod)
    .fail(function(){
        alert( 'one or more requests failed.' );
});

By default, following methods (then,done and fail) are available to all deferreds.

.then( doneCallbacks, failedCallbacks )

.done( doneCallbacks )

.fail( failCallbacks )

For convenience and consistency with the callback names, AJAX deferreds have three additional methods


var req = $.get('request.htm')
   .success(function() { alert("success"); })
  .error(function() { alert("error"); })
  .complete(function() { alert("complete"); });
  
doSomething();

req.success(function() { alert("Again success."); });

"success" and "error" map to "done" and "fail" respectively and a "complete " handler that'll fire regardless of the success or failure state of the request.

So, deferred provides a new approach. In old way, we need to combine all individual actions and pass it in callback function. Now, multiple actions can be performed in callback queues. In above example, there are multiple success callbacks. All are executed in queue order regardless the position of definition. It helps to write asynchronous code.

Hope, It helps.