JQuery Deferreds and Promises

The Deferred Object :

http://jsfiddle.net/shivanshu/7gnnA/

The “Deferred” pattern describes an object which acts as a proxy for some unit of computation that may or may not have completed.
In their simplest form, deferreds allow you to specify what will occur when a computation completes or fails. jQuery’s specific implementation allows you to register callback functions that will run if a deferred resolves successfully, if it is rejected with errors, or if it is notified of some “progress” towards a resolved state

A deferred object starts in a pending state, this means it is not yet completed. While in the pending state if the resolve() function is called then the state is changed to resolved, and if the reject() function is called then the state is changed to rejected.

Promise : Creating A Safety Net Around Our Deferred Object :

We can protect our Deferred objects from state changes by other code by creating a Promise object for the Deferred using the deferred.promise() method.

The promise exists purely for encapsulation: If you return a Deferred from a function, it might be resolved or rejected by the caller. But if you only return the pure Promise corresponding to that Deferred, the caller can only read its state and attach callbacks.

promise-validation-promise

Working with jQuery Deferred :

Creating Deffered Object :

// create a new deferred

// With the new special operator
var deferredObj = new $.Deferred();

//the new operator is optional.
var deferredObj = $.Deferred();

Binding Callbacks To Our Deferred Objects :

We can bind callbacks to our Deferred objects through the deferred.then(), deferred.done(), deferred.fail(), deferred.always(), deferred.pipe() and deferred.progress() methods.

var ourDeferred = $.Deferred();
// Our callbacks

//success
deferredObj.done( doneCallbacks );

//failure
deferredObj.fail( failCallbacks );

//progress
deferredObj.progress( progressCallbacks );

//Or We can also achieve the same using the deferred.then() shorthand method
deferredObj.then( doneCallbacks, failCallbacks, progressCallbacks );

Changing the state of Our Deferred Objects :

  • Success :
  • deferredObj.resolve();
    
  • Failure :
  •  dfd.reject();
    

    Complete code :

    // create a new deferred
    var dfd = $.Deferred();
    
     dfd.done( function() {
      alert( 'done!');
     });
    
     dfd.resolve();
    

    Passing parameters to resolve and reject :
    The arguments given to the resolve() or the fail() functions are passed to the callbacks so the object that resolved or failed the deferred object can be used.

    // create a new deferred
    var dfd = $.Deferred();
    
     dfd.done( function( data ) {
      alert( 'done!' + data );
     });
    
     dfd.resolve( 'yay!' );
    

    All these functions return the deferred object so they can be chained together to make the code more concise, like this:

    $.Deferred().done(function( data ) {
      alert( 'done!' + data );
     }).resolve('hello');
    

    Working with jQuery Promise :

    Creating Promise Object :

    // create a new deferred
    var dfd = $.Deferred();
    
    //get promise from deffred
    var prom = dfd.promise();
    

    Binding Callbacks To Our Promise Objects :

    We can bind callbacks to our Deferred objects through the deferred.then(), deferred.done(), deferred.fail(), deferred.always(), deferred.pipe() and deferred.progress() methods.

    var ourDeferred = $.Deferred();
    var ourPromise = ourDeferred.promise();
    // Our callbacks
    
    //success
    ourPromise.done( doneCallbacks );
    
    //failure
    ourPromise.fail( failCallbacks );
    
    //progress
    ourPromise.progress( progressCallbacks );
    
    //Or We can also achieve the same using the deferred.then() shorthand method
    ourPromise.then( doneCallbacks, failCallbacks, progressCallbacks );
    

    We can’t change the state through Promise

    Complete code :

    var dfd = $.Deferred();
    var prom = dfd.promise();
     prom.done( function( data ) {
      alert( 'done!' + data );
     });
     dfd.resolve( 'yay!' );
    

    Deffered Vs Promise

    DefAndPr

    promises

    creating defferd from your function :

    function someFunction() {
     var deferred = $.Deferred();
     // async wait 2 seconds:
     setTimeout(function () {
         alert('Inside function');
       deferred.resolve();
     }, 2000);
     return deferred.promise();
    };
    
    someFunction()
     .done(function () {
     alert('return from function');
     });
    

    Note :

    Resolving multiple jQuery deferreds using $.when

    $.when provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.

    function someFunction1(message) {
     var deferred = $.Deferred();
     // async wait 2 seconds:
     setTimeout(function () {
         alert('In first function: ' + message);
       deferred.resolve(message);
     }, 2000);
     return deferred.promise();
    };
    
    function someFunction2(message) {
     var deferred = $.Deferred();
     // async wait 2 seconds:
     setTimeout(function () {
         alert('In second function: ' + message);
       deferred.resolve(message);
     }, 2000);
     return deferred.promise();
    };
    
    $.when(someFunction1('foo'), someFunction2('bar'))
     .done(function (argFoo, argBar) {
     alert('return from first function: ' + argFoo);
     alert('return from second function: ' + argBar);
     });
    

    In the case where multiple Deferred objects are passed to jQuery.when, the method returns the Promise from a new “master” Deferred object that tracks the aggregate state of all the Deferreds it has been passed. The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected. If the master Deferred is resolved, it is passed the resolved values of all the Deferreds that were passed to jQuery.when. For example, when the Deferreds are jQuery.ajax() requests, the arguments will be the jqXHR objects for the requests, in the order they were given in the argument list.

    In the multiple-Deferreds case where one of the Deferreds is rejected, jQuery.when immediately fires the failCallbacks for its master Deferred. Note that some of the Deferreds may still be unresolved at that point. If you need to perform additional processing for this case, such as canceling any unfinished ajax requests, you can keep references to the underlying jqXHR objects in a closure and inspect/cancel them in the failCallback.

    If any of the deferreds are rejected, then the entire $.when will fail. In this case, the .fail callback function is called.

    function someFunction1(message) {
     var deferred = $.Deferred();
     // async wait 2 seconds:
     setTimeout(function () {
         alert('In first function: ' + message);
       deferred.reject(message);
     }, 2000);
     return deferred.promise();
    };
    
    function someFunction2(message) {
     var deferred = $.Deferred();
     // async wait 2 seconds:
     setTimeout(function () {
         alert('In second function: ' + message);
       deferred.reject(message);
     }, 2000);
     return deferred.promise();
    };
    
    
    $.when(someFunction1('foo'), someFunction2('bar'))
     .done(function (argFoo, argBar) {
     alert('return from first function: ' + argFoo);
     alert('return from second function: ' + argBar);
     })
    .fail( function (error) {
        alert('Failed due to: '+error);  
    });
    

    Note :

    If a single argument is passed to jQuery.when and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately. The doneCallbacks are passed the original argument. In this case any failCallbacks you might set are never called since the Deferred is never rejected. For example:

    $.when( { testing: 123 } ).done(function( x ) {
      alert( x.testing ); // Alerts "123"
    });
    

    For more info https://api.jquery.com/jQuery.when/

    Advertisements

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s