The Deferred Object JQ Home  <<  JQ Advanced  <<  The Deferred Object

In this lesson we investigate the jQuery Deferred object and how to utilize it for use in our webpages.

The jQuery Deferred object allows us to place our callbacks into queues and manage those queues whilst monitoring and reacting to the state of any synchronous or asynchronous function within the queue. The Deferred object is chainable and the three states available and the functionality behind the object is based on the Promises/A specification. The three states of a Promise object adressed by this specification are mirrored in jQuery as follows:

Promises/A jQuery jQuery Summary
unfulfilledpendingWhen a Deferred object is constructed its initial state is pending. A Deferred object will stay in the pending state until it is resolved or rejected.

Any callbacks added to the Deferred object with the deferred.then(), deferred.done(), deferred.fail() or deferred.progress() methods are queued to be executed later.

Calling the deferred.notify() or deferred.notifyWith() methods executes any progressCallbacks that have been set via the deferred.then() or deferred.progress() methods. Callbacks are always executed in the order they were added.

Any calls to the deferred.notify() or deferred.notifyWith() after a Deferred is resolved or rejected, as well as any progressCallbacks added after this change of state are ignored.
fulfilledresolvedWhen a Deferred object enters the resolved state, it stays in that state.

Calling the deferred.resolve() or deferred.resolveWith() methods transitions the Deferred object into the resolved state and immediately executes any doneCallbacks that have been set via the deferred.done() or deferred.always() methods. Callbacks are always executed in the order they were added.

Any doneCallbacks added after the Deferred has entered the resolved state are executed as soon as they are added, using any arguments that were passed to the deferred.resolve() or deferred.resolveWith() methods.
failedrejectedWhen a Deferred object enters the rejected state, it stays in that state.

Calling the deferred.reject() or deferred.rejectWith() methods transitions the Deferred object into the rejected state and immediately executes any failCallbacks that have been set via the deferred.fail() or deferred.always() methods. Callbacks are always executed in the order they were added.

Any failCallbacks added after the Deferred has entered the rejected state are executed as soon as they are added, using any arguments that were passed to the the deferred.reject() or deferred.rejectWith() methods.

Creating Deferred Objects

Deferred objects can be created using the new special operator with the jQuery.Deferred() constructor or by using the jQuery.Deferred() constructor alone, which is the way we will create Deferred objects for this lesson.

The jQuery.Deferred() constructor can also be passed an optional function; this is called just before the constructor returns and is passed the constructed Deferred object as both the this object and as the first argument to the function. The called function can then attach callbacks using any of the Deferred object's chainable methods.

Examples of both methods of instantiation are shown below:


// With the new special operator
var deferredObj = new jQuery.Deferred( [initFunction] );

// Without the new special operator
var deferredObj = jQuery.Deferred( [initFunction] );

  • After creating a Deferred object, you can use any of the Deferred object methods by chaining directly on object creation, or saving the object to a variable and then invoking the Deferred object methods on that variable.

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

Examples of binding callbacks are shown below:


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

Creating A Safety Net Around Our Deferred Objects

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. We can pass around the Promise object instead of the Deferred in the knowledge that none of our callbacks get triggered until we want them to:


An example of creating a Promise we can use is shown below:


var deferredObj = $.Deferred();
var ourPromise = deferredObj.promise();
ourPromise.fail( bFunc )// ok
ourPromise.done( bFunc )// ok
ourPromise.resolve( bFunc )// NOT ok

Deferred / Promise Usage In The Real World

Deferreds are extremely useful for creating callback queues that are fired dependant upon state, which can be utilized in many ways:

  • From jQuery 1.5 all the jQuery Ajax methods return a jqXHR object, which is derived from a Deferred object. So why is this a big deal, why attach a call after an Ajax call has already fired? In a nutshell because of encapsulation. Rather than coding the application making our request to handle every eventuality, we can do this far more elegantly by just passing around a Deferred. Details of this type of usage of Deferreds is covered in the Ajax lessons
  • You can stack as many callbacks as required in jQuery which can lead to reduced code duplication and hence maintenance when some functionality is shared.
  • From jQuery 1.6 you can use the .promise() method on ordinary jQuery objects which can be useful for tracking animation effects. When used in this scenario the promise will always be resolved regardless of whether the animation completed successfully or was stopped.

In the example below when we press the button the first time, we fire off some animations. We use the the .promise() method which gets resolved when all the animations have completed. After this happens we fire off a message.


// Animation example
$(function(){
  $('#btn3').one('click', function(){
    $('#curry1').fadeIn();
    $('#curry2').slideDown('slow')
                .slideUp('fast');
    $('#curry3').fadeIn(2000)
                .fadeOut('fast');
    $('#curry1, #curry2, #curry3').promise()
                                  .done(function() {
      $('#div1').append('Animations completed!');
    });
  });
});
a picture of curry a picture of curry a picture of curry

Press the button below to action the above code:

Combining Deferreds Using The .when() Method.

We can use the .when() method for logically combining two or more deferreds. The .when() method acts like a logical AND for deferred resolution. In other words the Promise generated from the .when() method is resolved when all of the given deferreds are resolved, or rejected when any of the given deferreds is rejected. One practical use for this is checking the results of multiple Ajax calls and acting appropriately on resolution or rejection. We will see examples of this usage in the Ajax lessons.

We can also pass non-Deferred objects to the .when() method. These objects are treated like Deferred objects that have been resolved with the given value in the pertinent argument slot.

Coding Future Events Using The deferred.then() Method.

We can use the deferred.then() method to react to the outcome of asynchronous events.

This effectively allows us to pipe future deferreds based on the outcome of current deferred. Therefore we don't have to wait for one asynchronous function to end before deciding what to do after it has ended.

  • The filter functions used by the deferred.then() method can return either:
    • A new value to be passed along to the piped deferred deferred.progress(), deferred.done() or deferred.fail() callbacks. This effectively allows us to pipe future deferreds based on the outcome of current deferred. Therefore we don't have to wait for one asynchronous function to end before deciding what to do after it has ended.
    • Another observable object which will pass its resolved, rejected or notified status and values to the piped deferred's callbacks. If a non-deferred value or no value is returned from the piped deferred, then this will be immediately resolved, rejected or notified with the value dependant upon the outcome of the original Deferred object.

Deferred Object Constructor & Method Examples

For working examples of the Deferred object and all its methods click a link in the table below to go to that references examples.

Deferred Object Methods Description
jQuery.Deferred()Deferred object constructor for managing callback queues.
deferred.always()Add handlers to be called when the Deferred object is resolved or rejected.
deferred.done()Add handlers to be called when the Deferred object is resolved.
deferred.fail()Add handlers to be called when the Deferred object is rejected.
deferred.isRejected() **REMOVED**Establish if a Deferred object has been rejected.
deferred.isResolved() **REMOVED**Establish if a Deferred object has been resolved.
deferred.notify()Call any progressCallbacks on a Deferred object with the specified arguments.
deferred.notifyWith()Call any progressCallbacks on a Deferred object with the specified context and arguments.
deferred.pipe() **DEPRECATED**Utility method for filtering and/or chaining a Deferred.
deferred.progress()Add handlers to the Deferred object that are called on progress notification generation.
deferred.promise()Return the promise object for a Deferred.
deferred.reject()Reject a Deferred object and call any failCallbacks with the specified arguments.
deferred.rejectWith()Reject a Deferred object and call any failCallbacks with the specified context and arguments.
deferred.resolve()Resolve a Deferred object and call any doneCallbacks with the specified arguments.
deferred.resolveWith()Resolve a Deferred object and call any doneCallbacks with the specified context and arguments.
deferred.state()Determine the current state of a Deferred object.
deferred.then()Add handlers to the Deferred object that are called on resolution, rejection or progress.
.promise()Return a dynamically generated Promise that is resolved once all collection bound actions of a certain type have ended.

Lesson 7 Complete

In this lesson we looked at the the Deferred object.

Reference

Methods

Events - .one() method
Manipulation - .append() method
Deferred Object - jQuery.Deferred() method
Deferred Object - deferred.always() method
Deferred Object - deferred.done() method
Deferred Object - deferred.fail() method
Deferred Object - deferred.isRejected() method
Deferred Object - deferred.isResolved() method
Deferred Object - deferred.notify() method
Deferred Object - deferred.notifyWith() method
Deferred Object - deferred.pipe() method
Deferred Object - deferred.promise() method
Deferred Object - deferred.reject() method
Deferred Object - deferred.rejectWith() method
Deferred Object - deferred.resolve() method
Deferred Object - deferred.resolveWith() method
Deferred Object - deferred.state() method
Deferred Object - deferred.then() method
Deferred Object - .promise() method
Core - .when() method