jQuery.Deferred implements CommonJS Promises/A
It's a chainable utility object that can register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function.
##jQuery.Deferred Basics
var deferred = new $.Deferred();
-
done() - Adds a callback to the "done" queue.
-
fail() - Adds a callback to the "fail" queue.
-
resolve() - Executes all queued "done" callbacks with provided arguments.
-
reject() - Executes all queued "fail" callbacks with provided arguments.
var deferred = new $.Deferred();
deferred.done(function(message) { alert(message); });
deferred.resolve("Hello World!");
deferred.done(function(message) { also_gets_hello_world(message); }); // deferreds are immutable
jQuery ajax functions return XHR objects that act like deferred.
$.ajax("somefile", {
success: render,
error: errorMessage
});
Is equivalent to:
$.ajax("somefile")
.done(render)
.fail(errorMessage);
Decoupling Multiple callbacks.
$.ajax("somefile", function(data) {
save(data);
render(data);
});
var someFile = $.ajax("somefile").done(save);
someFile.done(render);
// if the asynchronous function has already finished then render executes immediately.
- Decoupling Multiple callbacks.
- Simplify Multiple Dependencies.
- No nested callbacks with pipe.
- Easy to mix with callbacks
##Simplify Multiple Dependencies with $.when
var file, image; $.ajax("file", function(data) { file = data; if (file && image) render([file, image]); });
$.ajax("image", function(data) { image = data; if (file && image) render([file, image]); });
Return deferred from your objects.
function ImagesLoaded() {
var deferred = $.Deferred();
loadImages(function() {
deferred.resolve();
});
return deferred;
}
$.when(ImagesLoaded(), $.ajax("menu_data"))
.then(drawMenu);
Using callbacks without deferred.
$.ajax("me/friends", function(friends)
{
getMovies(friends, function(movies) {
getTitles(movies, alert);
});
});
No nested callbacks with Deferred.pipe
$.ajax("me/friends")
.pipe(getMovies)
.pipe(getTitles)
.done(alert);
Pipe takes a function that returns a deferred. By returning a function
we are allowing for lazy execution.
First the callback way.
function getMovies(friends, callback) {
var movieCalls = [];
friends.forEach(function(friend) {
$.ajax("movies/" +
friend.id, function(movie) {
if (movieCalls.length == friends.length) {
callback(Array.concatMultiple(movieCalls));
}
});
});
Deferred, Cheaper than we thought ...
function getMovies() {
return
return $.ajax("movies/" +
friend.id); })).pipe(Array.concatMultiple);
}
Easy to mix with callbacks
function AsyncMessage(msg, delay, callback) { var deferred = new $.Deferred(); deferred.done(callback); setTimeout(function() { deferred.resolve(msg);
}, delay); return deferred; }
AsyncMessage("hi", 10, alert);
AsyncMessage("hi", 10).done(alert);
AsyncMessage("hi", 10, alert).done(alert);
What if we mixed all these together?
Decoupling Multiple callbacks.
Simplify Multiple Dependencies.
No nested callbacks with pipe.
Easy to mix with callbacks (legacy code)
We get loosely coupled code with simplified dependency handling
and fewer nested callbacks.