jQuery Deferred always() Method

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

What Is always()?

deferred.always() adds handlers that run when a Deferred is either resolved or rejected (since jQuery 1.6). Ideal for shared cleanup. Returns the Deferred so you can chain. Accepts a function or an array of functions.

Remember
dfd.done(onSuccess)     // resolve only
dfd.fail(onError)       // reject only
dfd.always(onCleanup)   // resolve OR reject

// Official AJAX-style cleanup:
$.get("test.php").always(function () {
  // hide spinner — ignore args
});
NeedUse
Shared cleanupdfd.always(fn)
Success onlydfd.done(fn)
Failure onlydfd.fail(fn)
Create a Deferred$.Deferred()

How to Use always()

Attach outcome-specific handlers, then one shared cleanup.

  1. Create a Deferred (or use a jqXHR from $.ajax() / $.get()).
  2. Register done() / fail() for success and error UI.
  3. Register always(fn) for cleanup that must run either way.
  4. Settle with resolve() / reject() (or wait for AJAX to finish).
PieceRequired?Role
Deferred / jqXHRYesObject that will settle
alwaysCallbacksYesFunction or array of functions
Return—Same Deferred (chainable)

Pseudocode

Pseudocode
dfd = Deferred (pending)
alwaysQueue = []

always(fn or [fn…]):
  append to alwaysQueue
  if dfd already settled:
    run fn now with settle args
  return dfd

resolve(args…) / reject(args…):
  mark settled
  run done OR fail handlers
  run alwaysQueue in order with args

Cheat Sheet

Keep these facts handy for Deferred cleanup.

TopicDetail
Syntaxdeferred.always( alwaysCallbacks [, alwaysCallbacks ] )
Runs whenResolved or rejected
Pending?Does not run while pending
ArgsSame as resolve/reject — often different shapes
Best forSpinners, locks, analytics — ignore args
Chainable?Yes — returns the Deferred
SincejQuery 1.6

Live Preview

Settle a Deferred with resolve or reject and watch done / fail / always fire.

Browser demo of deferred.always — same ideas as the examples below.

Result
done: OK
always: cleanup

jQuery Examples

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

Example 1 — Cleanup After Resolve

Register done() for success and always() for shared cleanup.

jQuery
var dfd = $.Deferred();

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

dfd.always(function () {
  console.log("always: request finished");
});

dfd.resolve("OK");
Try It Yourself

How It Works

  1. Create. $.Deferred() starts pending.
  2. Register. done for success; always for cleanup.
  3. Resolve. Success path runs first.
  4. Always. Cleanup runs after the success handler.

Example 2 — Cleanup After Reject

always() still runs when the Deferred is rejected — that is its main value.

jQuery
var dfd = $.Deferred();

dfd.fail(function (reason) {
  console.log("fail:", reason);
});

dfd.always(function () {
  console.log("always: cleanup runs anyway");
});

dfd.reject("Network error");
Try It Yourself

How It Works

  1. Register fail + always. Error UI and shared cleanup.
  2. Reject. Failure path triggers fail.
  3. Always still runs. Cleanup is not skipped on error.
  4. Why it helps. Avoid duplicating hide-spinner logic in both paths.

Example 3 — Classic done / fail / always Chain

Mirror the AJAX pattern: handle data, handle errors, then finalize.

jQuery
var dfd = $.Deferred();

dfd
  .done(function (data) {
    console.log("Profile:", data.name);
  })
  .fail(function (err) {
    console.warn("Request failed:", err);
  })
  .always(function () {
    console.log("Re-enable submit button");
  });

dfd.resolve({ name: "Alex" });
// → Profile: Alex
// → Re-enable submit button
Try It Yourself

How It Works

  1. Chain three handlers. Success, error, cleanup.
  2. Resolve with data. done reads data.name.
  3. Always ignores args. Just restores UI state.
  4. Same on reject. Try the Try-it lab to simulate an error path.

Example 4 — Hide a Loading Indicator

Show a spinner when work starts; hide it in always() either way.

jQuery
function loadItems() {
  var status = "Loading…";
  var dfd = $.Deferred();

  setTimeout(function () {
    dfd.resolve(["apple", "banana"]);
  }, 300);

  dfd
    .done(function (items) {
      status = items.join(", ");
      console.log("List:", status);
    })
    .fail(function () {
      status = "Could not load items.";
      console.log(status);
    })
    .always(function () {
      console.log("Spinner hidden");
    });
}

loadItems();
Try It Yourself

How It Works

  1. Start pending. Mark UI as loading.
  2. Async resolve. Items arrive after a short delay.
  3. Done updates content. List text is written.
  4. Always clears loading. Spinner cannot stick after settle.

Example 5 — Multiple always() Handlers

Register several cleanup callbacks; jQuery calls each in order.

jQuery
var dfd = $.Deferred();

dfd.always(function () {
  console.log("Log event");
});

dfd.always(function () {
  console.log("Release UI lock");
});

dfd.always(function () {
  console.log("Send analytics beacon");
});

dfd.resolve("finished");
Try It Yourself

How It Works

  1. Three registrations. Each always() queues one handler.
  2. Resolve. The Deferred settles successfully.
  3. Order preserved. Handlers run FIFO.
  4. Alternative. You can also pass an array: always([fn1, fn2]).

Edge Cases & Pitfalls

Check these before putting logic inside always().

args

Do not parse settle arguments

Resolve and reject payloads often differ. Keep argument-aware logic in done / fail.

pending

Never runs while pending

always() waits for settle. Attaching it early is fine — it queues until resolve/reject.

late

Late attach still runs

If the Deferred already settled, a new always() callback runs immediately (memory-style queues).

errors

Throwing inside always

An exception in one always handler can interrupt later always callbacks in the same settle pass — keep cleanup defensive.

finally

Not identical to Promise.finally

Similar idea, but always() is jQuery Deferred-specific and receives settle arguments (unlike native finally).

Browser Support

deferred.always() is part of jQuery’s Deferred API (since 1.6). It works in any browser where your jQuery build runs — the queue lives in jQuery, not as a separate browser API.

✓ jQuery 1.6+ · Browsers

jQuery deferred.always()

Supported in jQuery 1.6+, including 2.x and 3.x, across Chrome, Firefox, Safari, Edge, and other browsers with jQuery loaded.

100% With jQuery loaded
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
deferred.always() Browsers

Bottom line: Safe wherever jQuery 1.6+ is loaded. Use always() for shared cleanup; keep argument-aware work in done() / fail().

Performance Notes

OperationCostBest for
always(fn)O(1) queueRegistering cleanup
Settle + always handlersO(n)Running all always callbacks
Duplicated cleanup in done+fail2× code pathsAvoid — prefer one always

Registering always() is cheap. Cost shows up if cleanup does heavy DOM or network work. Keep always handlers light (hide spinner, unlock UI) and put expensive outcome-specific work in done / fail.

Key Takeaways

  • Role: run after resolve or reject — perfect for cleanup.
  • Args: prefer ignoring them; use done/fail for known shapes.
  • AJAX: chain .always() on jqXHR from $.get / $.ajax.
  • Pattern: done → fail → always for clean request UI.

One line: always() is the Deferred cleanup hook — run it whether you win or lose.

Frequently Asked Questions

always() registers a callback that runs when the Deferred settles — either resolved or rejected. Use it for shared cleanup such as hiding spinners or re-enabling buttons.
done() runs only on resolve; fail() only on reject. always() runs after either outcome. It does not run while the Deferred is still pending.
Usually no. Official docs warn that resolve and reject arguments are often different shapes. Prefer always() for side effects that ignore args; use done() or fail() when you need the well-known argument order.
Yes. jqXHR objects implement the Deferred interface, so you can chain .done(), .fail(), and .always() — a common pattern for UI cleanup.
Conceptually similar: both run after success or failure. always() is jQuery-specific; native finally() is the modern standard outside jQuery.
Yes. Pass multiple functions or call always() several times. Callbacks run in registration order when the Deferred settles.

Next: catch()

Learn the modern shorthand for attaching a rejection handler on a Deferred.

catch() 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