Microjournal
Making sense of $.Deferred as a Promise
March 9, 2015
Reconciling jQuery's $.Deferred object with the Promise mental model by looking at producer, forwarder, and receiver use cases.
jQuery's $.Deferred object often gets dismissed because it doesn't mirror the modern Promise API exactly, yet it still implements the CommonJS Promises/A spec and can be a useful primitive when you understand the producer/consumer split.
PromiseJS famously warns that “what jQuery calls a promise is totally different,” which is true in terms of ergonomics but not necessarily in terms of capability. jQuery's own docs can also be dense, focusing on deferred.then(), deferred.done(), and deferred.fail() without clearly explaining how resolve/reject fit into the bigger picture.
The clearest framing came from an old StackOverflow answer that breaks the mental model down into two parts:
A deferred object can create a promise and change its state. You use it when you produce a value. A promise is the read-only side that receives the future value—you cannot modify its state.
Producer model
You create a deferred when your own function needs to expose asynchronous work as a promise.
function callMe() {
var deferred = new $.Deferred();
setTimeout(function () {
deferred.resolve("some_value_compute_asynchronously");
}, 1000);
return deferred.promise();
}
callMe().done(function (value) {
alert(value);
});
Forward model
If the function you call already returns a promise, simply return that promise without introducing another deferred.
function fetchData() {
// configure $.ajax and return the promise it gives you
return $.ajax({ /* ... */ });
}
fetchData().done(function (response) {
// handle the server response
});
Receiver / chaining model
When you merely react to a promise (the consumer side), you chain handlers without touching the deferred at all.
$("#my_element").fadeOut().promise().done(function () {
console.log("Animation finished");
});
The takeaway: jQuery's promises are not identical to the native Promise implementation, but they still give you a clear producer/consumer contract. For most legacy jQuery apps that already ship the library, leaning on $.Deferred avoids the overhead of introducing another Promise polyfill while still delivering predictable async flows.