jQuery 1.5 brings the new Deferred object and the attached methods .when
, .Deferred
and ._Deferred
.
For those who haven'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.
I am particularly interested in what techniques are available when we abstract away whether an operation is synchronously or asynchronously done.
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:
var cache = {};
function getData( val ){
// return either the cached value or jqXHR object wrapped Promise
return $.when(
cache[ val ] ||
$.ajax('/foo/', {
data: { value: val },
dataType: 'json',
success: function( resp ){
cache[ val ] = resp;
}
})
);
}
getData('foo').then(function(resp){
// do something with the response, which may
// or may not have been retrieved using an
// XHR request.
});
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:
$.when($.getJSON('/some/data/'), $.get('template.tpl')).then(function (data, tmpl) {
$(tmpl) // create a jQuery object out of the template
.tmpl(data) // compile it
.appendTo("#target"); // insert it into the DOM
});