jQuery 1.5 brings the new Deferred object and the attached methods .when
, .Deferred
and ._Deferred
.
For those who havn't used .Deferred
before I've annotated the source for it
What are the possible usages of these new methods, how do we go about fitting them into patterns?
I have already read the API and the source, so I know what it does. My question is how can we use these new features in everyday code?
I have a simple example of a buffer class that calls AJAX request in order. (Next one start after previous one finishes).
/* Class: Buffer
* methods: append
*
* Constructor: takes a function which will be the task handler to be called
*
* .append appends a task to the buffer. Buffer will only call a task when the
* previous task has finished
*/
var Buffer = function(handler) {
var tasks = [];
// empty resolved deferred object
var deferred = $.when();
// handle the next object
function handleNextTask() {
// if the current deferred task has resolved and there are more tasks
if (deferred.isResolved() && tasks.length > 0) {
// grab a task
var task = tasks.shift();
// set the deferred to be deferred returned from the handler
deferred = handler(task);
// if its not a deferred object then set it to be an empty deferred object
if (!(deferred && deferred.promise)) {
deferred = $.when();
}
// if we have tasks left then handle the next one when the current one
// is done.
if (tasks.length > 0) {
deferred.done(handleNextTask);
}
}
}
// appends a task.
this.append = function(task) {
// add to the array
tasks.push(task);
// handle the next task
handleNextTask();
};
};
I'm looking for demonstrations and possible uses of .Deferred
and .when
.
It would also be lovely to see examples of ._Deferred
.
Linking to the new jQuery.ajax
source for examples is cheating.
Bounty: Show us what techniques are available when we abstract away whether an operation is synchronously or asynchronously done.
This is a self-promotional answer, but I spent a few months researching this and presented the results at jQuery Conference San Francisco 2012.
Here is a free video of the talk:
http://www.confreaks.com/videos/993-jqcon2012-i-promise-to-show-you-when-to-use-deferreds
Another example using
Deferred
s to implement a cache for any kind of computation (typically some performance-intensive or long-running tasks):Here is an example of using this class to perform some (simulated heavy) calculation:
The same underlying cache could be used to cache Ajax requests:
You can play with the above code in this jsFiddle.
I've just used Deferred in real code. In project jQuery Terminal I have function exec that call commands defined by user (like he was entering it and pressing enter), I've added Deferreds to the API and call exec with arrays. like this:
or
the commands can run async code, and exec need to call user code in order. My first api use pair of pause/resume calls and in new API I call those automatic when user return promise. So user code can just use
or
I use code like this:
dalyed_commands is used in resume function that call exec again with all dalyed_commands.
and part of the commands function (I've stripped not related parts)
The best use case I can think of is in caching AJAX responses. Here's a modified example from Rebecca Murphey's intro post on the topic:
Basically, if the value has already been requested once before it's returned immediately from the cache. Otherwise, an AJAX request fetches the data and adds it to the cache. The
$.when
/.then
doesn't care about any of this; all you need to be concerned about is using the response, which is passed to the.then()
handler in both cases.jQuery.when()
handles a non-Promise/Deferred as a Completed one, immediately executing any.done()
or.then()
on the chain.Deferreds are perfect for when the task may or may not operate asynchronously, and you want to abstract that condition out of the code.
Another real world example using the
$.when
helper:1) Use it to ensure an ordered execution of callbacks:
2) Use it to verify the status of the app: