jQuery Deferred progress() Method

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

What Is progress()?

deferred.progress() adds handlers that run when the Deferred sends progress notifications with notify() or notifyWith(). It is available since jQuery 1.7 and returns the same Deferred for chaining.

Remember
deferred.progress(progressCallbacks)

progress()  → listen for updates
notify()    → emit an update (owner)
done()      → final success
fail()      → final failure

progress can run many times while pending
native Promise has no progress API
NeedUse
Listen for updatesdfd.progress(fn)
Emit an updatedfd.notify(value)
Finish successfullydfd.done(fn)

How to Use progress()

Register listeners first, emit updates with notify(), then settle.

  1. Create a Deferred (or receive one from an async helper).
  2. Call progress(fn) — optionally add more handlers or arrays of handlers.
  3. While work runs, call notify(args…) to fire those handlers.
  4. When finished, resolve() or reject() — then use done() / fail().
PieceRequired?Role
progressCallbacksYesFunction or array of functions
Extra callback argsOptionalMore functions / arrays on the same call
Return—Same Deferred (chainable)
Since—jQuery 1.7

Pseudocode

Pseudocode
dfd = Deferred
handlers = []

progress(fn):
    append fn to handlers
    if dfd already resolved or rejected:
        call fn immediately with last notify args
    return dfd

notify(args…):
    if dfd still pending:
        for each handler: handler(args…)
        remember args as last notify

resolve / reject:
    settle dfd
    // further notify() does not call progress handlers

Cheat Sheet

Keep these facts handy while wiring progress updates.

TopicDetail
Syntaxdeferred.progress(fn [, fn…])
Triggernotify() / notifyWith()
vs done()Many updates vs one success
ArraysPass a function or an array of functions
After settleNo new notify; late progress(fn) runs once with last args
Native PromiseNo built-in progress channel
SincejQuery 1.7

Live Preview

Pick a demo to see how progress() reacts to notify() and settlement.

Browser demo of deferred.progress — same idea as the examples below.

Result
Progress: 50% complete
Progress: 90% complete
Done: Operation completed successfully

/* notify → progress; resolve → done */

jQuery Examples

Short, copy-ready snippets. Open the browser console, or use Try It Yourself for a live editor.

Example 1 — Status Message Updates

Register progress(), receive two notify() calls, then resolve().

jQuery
var dfd = $.Deferred();

dfd.progress(function (message) {
  console.log("Progress:", message);
});

dfd.done(function (result) {
  console.log("Done:", result);
});

dfd.notify("50% complete");
dfd.notify("90% complete");
dfd.resolve("Operation completed successfully");
Try It Yourself

How It Works

  1. Attach listeners. progress and done are registered while pending.
  2. First notify. The progress handler logs 50% complete.
  3. Second notify. Same handler runs again with 90% complete.
  4. Resolve. State becomes resolved; done logs the final message.

Example 2 — Percent Steps

Pass numbers through notify() to drive a simple percent log (or a UI bar).

jQuery
var dfd = $.Deferred();

dfd.progress(function (percent) {
  console.log("Upload:", percent + "%");
});

dfd.done(function () {
  console.log("Upload finished");
});

[25, 50, 75, 100].forEach(function (pct) {
  dfd.notify(pct);
});

dfd.resolve();
Try It Yourself

How It Works

  1. One handler. It expects a number from each notify.
  2. Loop. Four percentages each call notify(pct).
  3. Log each step. The handler prints Upload: N%.
  4. Finish. resolve() runs done after the last update.

Example 3 — Multiple Progress Handlers

Every notify() calls each registered progress callback.

jQuery
var dfd = $.Deferred();

dfd.progress(function (step) {
  console.log("A:", step);
});

dfd.progress(function (step) {
  console.log("B:", step);
});

dfd.notify("loading");
dfd.resolve("ok");
Try It Yourself

How It Works

  1. Register two handlers. Both sit in the progress queue.
  2. One notify. jQuery invokes A, then B, with "loading".
  3. Same args. Each handler receives the notify arguments.
  4. Resolve separately. Progress and done are independent phases.

Example 4 — Late progress() After Resolve

After settle, new notify() is ignored — but a late progress() runs once with the last notify args.

jQuery
var dfd = $.Deferred();

dfd.notify("last update");
dfd.resolve("done");

dfd.progress(function (msg) {
  console.log("Late:", msg);  // Late: last update
});

dfd.notify("ignored");  // no progress call
Try It Yourself

How It Works

  1. Notify then resolve. The Deferred stores the last progress args and settles.
  2. Add progress late. Official rule: the new callback runs immediately with those last args.
  3. Log once. You see Late: last update.
  4. Notify after settle. Further notify() does not call progress handlers.

Example 5 — progress + done + fail

Wire the full story: updates along the way, then success or failure.

jQuery
var dfd = $.Deferred();

dfd.progress(function (n) {
  console.log("step", n);
}).done(function (result) {
  console.log("ok", result);
}).fail(function (err) {
  console.log("err", err);
});

dfd.notify(1);
dfd.notify(2);
dfd.resolve("finished");
// dfd.reject("stopped");  // use instead of resolve to test fail
Try It Yourself

How It Works

  1. Chain handlers. progress returns the Deferred, so done / fail chain cleanly.
  2. Notify twice. Progress logs step 1 and step 2.
  3. Resolve. done logs ok finished; fail stays idle.
  4. Try reject. Swap to reject to see the fail path instead.

Edge Cases & Pitfalls

Check these before relying on progress() in real projects.

order

Register before notify

Handlers attached after a notify() miss that update (unless the Deferred already settled — then late progress replays the last args only).

settle

No progress after settle

Once resolved or rejected, further notify() calls do not invoke progress handlers.

promise

Promise consumers cannot notify

Give callers promise() so they can attach progress / done but cannot call notify or resolve.

native

Not in native Promises

progress / notify are jQuery Deferred features. Do not expect the same API on Promise.

Browser Support

deferred.progress() needs jQuery 1.7+ loaded. It works in jQuery 1.7–3.x alongside notify() / notifyWith().

✓ jQuery 1.7+

deferred.progress()

Works in Chrome, Firefox, Safari, and Edge when jQuery 1.7+ is loaded. Pair with notify() to emit updates.

100% With jQuery 1.7+
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
progress() Universal

Bottom line: Safe wherever jQuery 1.7+ Deferreds are available. Remember: native Promises have no progress channel.

Performance Notes

ApproachCostBest for
progress + rare notifyCheapStep labels, coarse percent
notify every tickCan flood UIThrottle (e.g. every 5–10%)
done / fail onlyCheapestWhen mid-flight UI is not needed

Progress handlers are ordinary callbacks. Avoid notifying on every byte or animation frame unless the UI can keep up — batch or throttle updates.

Key Takeaways

  • Role: listen for interim notify() updates.
  • Pair: progress for updates, done/fail for the end.
  • Chain: returns the same Deferred — stack more handlers freely.
  • Late attach: after settle, progress(fn) runs once with last notify args.

One line: progress() listens; notify() speaks — use them for mid-flight updates before done or fail.

Frequently Asked Questions

progress() adds handlers that run when the Deferred generates progress notifications via notify() or notifyWith(). It does not settle the Deferred — resolve() and reject() still control the final outcome.
done() runs once on successful resolve. progress() can run many times while the Deferred is pending. Use progress for interim updates; use done for the finish.
notify() and notifyWith() on the same Deferred. Each call invokes every registered progress callback with the arguments you passed.
Yes. progress() accepts a function or an array of functions, and you may pass multiple arguments (each a function or array).
New notify() calls no longer fire progress handlers after settlement. But a progress callback added after resolve/reject runs immediately with the arguments from the last notify()/notifyWith().
No. Progress notifications are a jQuery Deferred feature. Native Promises only fulfill or reject — use separate callbacks, events, or other patterns for mid-flight updates.

Next: deferred.promise()

Learn how to share a read-only promise so callers can listen but not settle.

promise() 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.

9 people found this page helpful