The progress() method registers callbacks that run when notify() sends interim updates. Use it for progress bars, step labels, and status text while a Deferred is still pending — then handle the final result with done() or fail().
01
Syntax
dfd.progress(fn)
02
notify()
Triggers handlers
03
Pending
Not final state
04
Multiple
Many handlers OK
05
vs done()
Updates vs finish
06
Since 1.7
With notify API
Fundamentals
Introduction
Success and failure callbacks tell users how a task ended — but long operations also need mid-flight feedback. jQuery’s progress() method listens for notify() pings: percentage complete, current step, or any status message emitted while the Deferred remains pending.
Think of the trio as a complete async story: progress() for updates, done() for success, fail() for errors.
Concept
Understanding the progress() Method
progress() is part of jQuery’s Deferred Object API (since jQuery 1.7). Calling deferred.progress(callback) adds your function to a progress queue. Each time the Deferred owner calls notify() or notifyWith(), jQuery invokes every progress handler with the notify arguments.
Progress handlers do not change Deferred state. The operation stays pending until resolve() or reject() runs — only then do done() or fail() fire.
💡
Beginner Tip
Register progress()before the first notify(), just like attaching done() before resolve(). The reference example does this correctly — our examples also call resolve() at the end so done() confirms completion.
Register handlers first, then emit progress as async milestones arrive. The final timer calls resolve() so users see both interim updates and completion.
Applications
🚀 Use Cases
File uploads — update a progress bar as bytes are sent.
Multi-step wizards — show “Step 2 of 5” as each stage completes.
Data imports — log row counts or batch numbers during processing.
Long computations — report iteration progress without blocking the UI thread.
Loading indicators — swap spinner text from “Loading…” to specific status messages.
🧠 How progress() Fits the Deferred Lifecycle
1
Register
dfd.progress(fn) queues handlers while state is pending.
Listen
2
Notify
Owner calls notify() — every progress handler runs.
Update
3
Settle
resolve() or reject() — done() or fail() runs.
Finish
=
📈
Informed user
Progress during work, final message via done() or fail().
Important
📝 Notes
progress() only runs when notify() or notifyWith() is called — it does not fire on resolve or reject alone.
Register handlers before the first notify for predictable behavior.
Put final success logic in done(), not progress().
Consumers with only a promise() view can attach progress() but cannot call notify().
Native Promises have no progress() — this is jQuery-specific.
Compatibility
Browser Support
deferred.progress() has been available since jQuery 1.7 alongside notify(). It works wherever jQuery Deferred runs.
✓ jQuery 1.7+
jQuery Deferred.progress()
Supported in jQuery 1.7+, 2.x, and 3.x. Progress listeners are a jQuery extension — not part of the native Promise standard.
100%With jQuery loaded
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
deferred.progress()Universal
Bottom line: Pair progress() with notify() for jQuery long-running tasks. For non-jQuery apps, use events or other progress patterns.
Wrap Up
🎉 Conclusion
The deferred.progress() method listens for interim updates on jQuery Deferreds. Register handlers early, pair them with notify() from the task owner, and finish with done() or fail() for the final outcome.
Next, explore promise() to expose a read-only view of a Deferred, or review notify() for the emitter side of progress.
How to listen for jQuery Deferred progress updates.
5
Core concepts
📝01
Syntax
dfd.progress(fn)
API
📢02
notify()
Triggers fn
Pair
⏰03
Pending
Interim only
State
📈04
Many calls
Per notify
Repeat
done05
Then done
Final result
Finish
❓ Frequently Asked Questions
progress() registers a callback that runs whenever notify() or notifyWith() sends a progress update. The Deferred stays pending until resolve() or reject() — progress handlers report interim status, not final outcome.
done() runs once when the Deferred resolves successfully. progress() can run many times while work is still in progress. done() handles the finish line; progress() handles updates along the way.
Calls to notify() and notifyWith() on the same Deferred. Each notify fires every registered progress callback with the arguments passed to notify.
Yes. jQuery queues them and invokes each one on every notify(), similar to multiple done() handlers on resolve.
No new progress events fire after settlement. Register progress() before notify() calls, and send all progress updates before resolve() or reject().
No. progress() is a jQuery Deferred extension paired with notify(). Native Promises only support fulfillment and rejection — use events, callbacks, or Observables elsewhere for progress.
Did you know?
jQuery’s progress API was inspired by the need for upload indicators before modern fetch and native Promises existed. The listener (progress) and emitter (notify) split keeps consumers from accidentally settling someone else’s Deferred.