deferred.then(doneFilter [, failFilter] [, progressFilter]) adds handlers for resolve, reject, and progress. Since jQuery 1.8 it returns a new Promise that can transform status and values.
Remember
dfd.then(onDone, onFail, onProgress)
// Filter resolve value
dfd.then(function (v) { return v * 2; })
// Fail only
dfd.then(null, onFail)
// Returns a NEW Promise (chainable)
Attach filters, optionally transform the value, then continue the chain.
Start from a Deferred or jqXHR (e.g. $.get).
Call .then(doneFilter, failFilter) — pass null to skip a slot.
Return a value or another Promise from the filter to feed the next step.
Chain more .then() / .done() / .fail() on the returned Promise.
Piece
Required?
Role
doneFilter
Optional
Runs on resolve; may transform value
failFilter
Optional
Runs on reject; may transform reason
progressFilter
Optional
Runs on notify / notifyWith
Return value
—
New Promise (not the same Deferred)
Pseudocode
Pseudocode
function then(deferred, doneFilter, failFilter, progressFilter):
promise = new Promise linked to deferred
when deferred resolves(value):
if doneFilter:
next = doneFilter(value)
settle promise from next (value or another promise)
else:
resolve promise with value
// similar for reject → failFilter, notify → progressFilter
return promise
Create a Deferred and a filtered Promise via then.
Filter multiplies the resolved value by 2.
Resolve(5) on the original → filtered Promise gets 10.
done on filtered prints the transformed value.
Example 3 — Filter a Rejection (Recover)
Pass null for success; in jQuery 3+, returning a value from the fail filter recovers the chain.
jQuery
var defer = $.Deferred();
var filtered = defer.then(null, function (value) {
return value * 3; // recover with a new value
});
filtered.done(function (value) {
console.log("recovered (3*6=) 18: " + value);
});
defer.reject(6);
// recovered (3*6=) 18: 18
Unlike done(), you must keep the return value to continue the filtered chain. Chaining on the original Deferred skips your transforms.
side-effect
Do not expect done to transform
Values returned from done()/fail() are ignored. Use then() when the next step needs a new value.
null
Pass null to skip a filter
then(null, failFilter) leaves resolve values unchanged while still filtering rejects.
legacy
Pre-1.8 signatures are gone
Old then(doneCallbacks, failCallbacks) array forms were removed in 1.8. Current jQuery expects filter functions.
Compatibility
Browser Support
deferred.then() exists since jQuery 1.5; the filter/Promise signature is from 1.8. jQuery 3+ aligns chaining with Promises/A+. Works in all modern browsers with jQuery loaded.
✓ jQuery 1.8+ filters
deferred.then()
Supported everywhere jQuery Deferred runs. Prefer the 1.8+ filter form for transforms and chains.
100%Browser support
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
then()Excellent
Bottom line: Use dfd.then(doneFilter, failFilter) to transform and chain. Prefer it over deprecated pipe().
Analysis
Performance Notes
Approach
Cost
Best for
then(fn)
O(k) + new Promise
Transforms / pipelines
done(fn)
O(k)
Side effects only
Deep chains
More promises
Keep steps clear; avoid unused links
Promise allocation is usually tiny next to network or DOM work. Choose then for clarity when values must flow; use done for simple logging/UI.
Remember
Key Takeaways
Role: filter resolve/reject/progress and return a new Promise.
One line:dfd.then(fn) builds a new Promise that can transform success, failure, and progress — use it to chain, not just to listen.
Frequently Asked Questions
then(doneFilter, failFilter, progressFilter) attaches handlers for resolve, reject, and progress. Since jQuery 1.8 it returns a new Promise that can filter or transform values — replacing the deprecated pipe() method.
done() and fail() only run side effects; their return values are ignored. then() filters the chain: returned values (or promises) flow to the next link, and then() itself returns a new Promise.
Yes. As of jQuery 1.8, then() provides pipe-style filtering. pipe() is deprecated in jQuery 3+ — prefer then() for new code.
A plain value (passed downstream), another Deferred/Promise (the chain waits), or a rejection (throw / rejected promise) to fail the next step.
Yes. Pass null for unused slots, e.g. then(null, failFilter) to only transform rejections.
Since jQuery 3.0, Deferred promises are Promises/A+ compatible for chaining and error bubbling, with jQuery extras like progress still available on Deferreds.