jQuery Deferred then() Method

Beginner
7 min read
Updated: Oct 2026
4 examples
Live preview

What Is then()?

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)
NeedUse
Transform / chaindfd.then(fn)
Side effect onlydone() / fail()
Legacy filter APIpipe() (deprecated)

How to Use then()

Attach filters, optionally transform the value, then continue the chain.

  1. Start from a Deferred or jqXHR (e.g. $.get).
  2. Call .then(doneFilter, failFilter) — pass null to skip a slot.
  3. Return a value or another Promise from the filter to feed the next step.
  4. Chain more .then() / .done() / .fail() on the returned Promise.
PieceRequired?Role
doneFilterOptionalRuns on resolve; may transform value
failFilterOptionalRuns on reject; may transform reason
progressFilterOptionalRuns 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

Cheat Sheet

Keep these facts handy while chaining Deferreds.

TopicDetail
Syntax (1.8+)then(doneFilter [, failFilter] [, progressFilter])
ReturnsNew Promise
vs done/failthen filters; done/fail do not
Skip a filterPass null
ReplaceUse instead of deprecated pipe()
Pre-1.8Old callback-array signatures removed

Live Preview

Pick a scenario and see how then() filters resolve or reject.

Browser demo of deferred.then() — same ideas as the examples below.

Result
success: ok

jQuery Examples

Short, copy-ready snippets. Open DevTools Console, or use Try It Yourself for a live editor.

Example 1 — Success and Failure Handlers

Official style: two callbacks like $.get(...).then(ok, err).

jQuery
var dfd = $.Deferred();

dfd.then(
  function (msg) {
    console.log("success: " + msg);
  },
  function (err) {
    console.log("error: " + err);
  }
);

dfd.resolve("ok");
// success: ok
Try It Yourself

How It Works

  1. Two filters. First runs on resolve; second on reject.
  2. Resolve with "ok" — only the success path runs.
  3. Reject instead would call the second function.
  4. Same idea as pairing done + fail, but returns a Promise.

Example 2 — Filter the Resolve Value

Return a new value from then; downstream handlers see the filtered result.

jQuery
var defer = $.Deferred();
var filtered = defer.then(function (value) {
  return value * 2;
});

filtered.done(function (value) {
  console.log("Value is (2*5=) 10: " + value);
});

defer.resolve(5);
// Value is (2*5=) 10: 10
Try It Yourself

How It Works

  1. Create a Deferred and a filtered Promise via then.
  2. Filter multiplies the resolved value by 2.
  3. Resolve(5) on the original → filtered Promise gets 10.
  4. 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
Try It Yourself

How It Works

  1. null doneFilter — success path is unfiltered.
  2. failFilter runs on reject and returns 6 * 3.
  3. Promises/A+ (jQuery 3+) — a returned value fulfills the next Promise.
  4. done on filtered receives 18 (chain recovered).

Example 4 — Chain Transforms

Each then returns a new Promise — build a short pipeline.

jQuery
var dfd = $.Deferred();

dfd
  .then(function (n) { return n + 1; })
  .then(function (n) { return n * 10; })
  .done(function (n) {
    console.log(n);  // 40
  });

dfd.resolve(3);
// 3 → 4 → 40
Try It Yourself

How It Works

  1. Resolve 3 starts the pipeline.
  2. First then returns 3 + 1 → 4.
  3. Second then returns 4 * 10 → 40.
  4. done sees the final filtered value.

Edge Cases & Pitfalls

Avoid these mistakes when chaining with then().

return

then returns a new Promise

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.

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 Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
then() Excellent

Bottom line: Use dfd.then(doneFilter, failFilter) to transform and chain. Prefer it over deprecated pipe().

Performance Notes

ApproachCostBest for
then(fn)O(k) + new PromiseTransforms / pipelines
done(fn)O(k)Side effects only
Deep chainsMore promisesKeep 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.

Key Takeaways

  • Role: filter resolve/reject/progress and return a new Promise.
  • Transform: return values (or promises) flow downstream.
  • vs done/fail: those ignore return values.
  • Legacy: prefer then over deprecated pipe().

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.

Next: pipe()

See the legacy filter API and why then() replaced it.

pipe() tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

10 people found this page helpful