jQuery .then() vs .done() and .fail()
In jQuery, managing asynchronous operations relies on the Deferred
and Promise APIs, where .then(), .done(), and
.fail() handle completion or rejection states. While
.done() and .fail() are legacy utility methods
designed simply to attach callbacks to an existing Deferred object,
.then() adheres more closely to modern Promises/A+
specifications by returning a new promise. Consequently,
.then() supports data transformation and sequential
asynchronous chaining, whereas .done() and
.fail() simply execute side effects while returning the
original Deferred object unchanged.
Understanding .done() and .fail()
The .done() and .fail() methods are
dedicated handlers for specific promise states:
.done(callback): Executes the provided callback function only when the Deferred object is successfully resolved..fail(callback): Executes the provided callback function only when the Deferred object is rejected.
Both methods return the original Deferred or Promise object to which
they were attached. Because the return value is the original object,
chaining multiple .done() or .fail() calls
attaches multiple independent listeners to the exact same event. They
cannot modify the values passed down the chain.
$.ajax("/api/user")
.done(function(data) {
console.log("Request succeeded:", data);
})
.fail(function(error) {
console.error("Request failed:", error);
});Understanding .then()
The .then() method accepts up to three arguments: a
success handler, a failure handler, and an optional progress
handler:
promise.then(doneCallback, failCallback);Starting in jQuery 1.8, .then() creates and returns a
new promise rather than returning the original Deferred
object. The value returned by the callback inside .then()
determines the resolved value of this new promise. This behavior allows
you to:
- Transform Data: You can return modified data from a
.then()handler, and subsequent chained methods will receive that modified data. - Chain Asynchronous Tasks: If a
.then()callback returns another promise, the downstream chain waits for that nested promise to resolve before continuing.
$.ajax("/api/user")
.then(function(user) {
// Transform data
return user.id;
})
.then(function(userId) {
// Returns a new AJAX promise
return $.ajax("/api/profile/" + userId);
})
.done(function(profile) {
console.log("Fetched profile:", profile);
});Key Differences
1. Return Values and Chaining
.done()and.fail(): Always return the same promise object. Any return statement inside their callbacks is ignored..then(): Returns a new promise object. The return value inside the callback is passed to the next handler in the chain.
2. Error Recovery and Filtering
Because .then() returns a new promise, throwing an error
or returning a rejected promise inside a .then() handler
changes the state of the downstream promise chain. In contrast,
.done() and .fail() do not alter state
transitions across chained calls.
3. Standards Compliance
Modern JavaScript uses native Promises, where .then()
and .catch() are standard. jQuery's .then()
mimics the standard Promise pipeline, making it easier to write code
that aligns with modern ECMAScript standards. The .done()
and .fail() methods are non-standard, jQuery-specific
constructs.
When to Use Which
- Use
.done()and.fail()when you only need simple, standalone handlers to react to the outcome of an event without modifying the output or chaining dependent asynchronous requests. - Use
.then()when you need sequential execution (calling one asynchronous operation after another) or when you need to transform the result before passing it to subsequent handlers.