Skip to content

Instantly share code, notes, and snippets.

@lukechinworth
Last active February 13, 2018 13:22
Show Gist options
  • Save lukechinworth/e1a35ccca39fcb1b2f83 to your computer and use it in GitHub Desktop.
Save lukechinworth/e1a35ccca39fcb1b2f83 to your computer and use it in GitHub Desktop.
jQuery Deferreds and Promises

Two ideas: Deferreds and Promises.

Part 1: Deferred

A Deferred object is initially pending. It can be either resolved or rejected. You can do so by literally calling .resolve or .reject on the Deferred object. You can check its state (pending, resolved, or rejected) by calling .state on it. Once it leaves pending (to be either resolved or rejected) it is permanently that state and cannot be undone (unless of course with a page refresh).

These states are nice because you can put code in functions that will only run when the Deferred object has been set to one of these states. This is done with the .done and .fail methods on the Deferred object. Two examples: the first to explain states, and the second to explain running code based on states.

Example 1:

var deferredObject = new $.Deferred(); //create a new Deferred object
deferredObject.resolve(); //resolve the Deferred object
deferredObject.state(); //check the state of the Deferred object, which is resolved
deferredObject.reject(); //try to reject but its state is already set to resolved
deferredObject.state(); //check the state. it is still resolved because its state can only be set once and it was set to resolved first

Example 2:

deferredObject.done(function() {
  //code to be run when deferredObject has been resolved
});

deferredObject.fail(function() {
  //code to be run when deferredObject has been rejected
});

Additionally, there is a .always method which will run its contained code once its Deferred object is resolved or rejected, or rather, once it leaves its pending state. For example:

deferredObject.always(function() {
  //code to be run when deferredObject has been either resolved or rejected
});

Rather than make three separate declarations for what to run for done, fail, or always (either case) like above, you can use the .then method to combine all three.

deferredObject.then(function() {
  //code to be run when deferredObject has been resolved
}, function() {
  //code to be run when deferredObject has been rejected
}, function() {
  //code to be run when deferredObject has been either resolved or rejected
});

These functions to be run based on the state of a Deferred object are referred to as callbacks.

Part 2: Promises

A Promise object is made from a Deferred object by calling .promise on it. (Made is maybe the wrong verb. It might be more like exposing the Promise object already inside the Deferred object) For example:

var promiseObject = deferredObject.promise();

A Promise is attached to the Deferred from which it came. You use the same Deferred methods as above on its Promise, except you can't use .resolve or .reject on a Promise. This is because when you check the state of a Promise, you are actually checking the state of its Deferred. So you can check the state of a Deferred through its Promise, but to change the state of the Deferred you have to go straight to it, not through its Promise. For example:

var deferredObject = new $.Deferred(); //create a new Deferred object
var promiseObject = deferredObject.promise();

promiseObject.state();  // state is pending because deferredObject's state has not been set yet
deferredObject.reject(); 
promiseObject.state();  // state is rejected because its parent deferredObject was rejected

In this way, the Promise is more secure than its Deferred.

This article helped me attain this understanding of Promises. I don't understand what .pipe is though. http://code.tutsplus.com/tutorials/wrangle-async-tasks-with-jquery-promises--net-24135 The jQuery docs for Promises were also helpful after I had a bit of understanding. https://api.jquery.com/deferred.promise/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment