jQuery Deferred always() Method

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Async cleanup

What You’ll Learn

The always() method attaches a callback that runs when a jQuery Deferred settles — whether the operation succeeded or failed. This tutorial covers syntax, five worked examples, comparisons with done() and fail(), and practical cleanup patterns for AJAX and custom async tasks.

01

Syntax

dfd.always(fn)

02

On resolve

Cleanup after success

03

On reject

Cleanup after failure

04

vs done/fail

Shared final step

05

AJAX

Hide spinners

06

Chainable

Returns Deferred

Introduction

Asynchronous work — AJAX calls, animations, timers — rarely finishes instantly. jQuery’s Deferred object lets you register handlers for success (done()), failure (fail()), and progress (progress()). The always() method fills a different role: it runs code you need no matter which outcome occurred.

Typical jobs for always() include hiding loading indicators, re-enabling submit buttons, closing modal overlays, and writing audit logs. Keep outcome-specific logic in done() or fail(); keep shared teardown in always().

Understanding the always() Method

always() is part of jQuery’s Deferred Object API. When you call deferred.always(callback), jQuery queues your function and invokes it once the Deferred enters a resolved or rejected state. It does not run while the operation is still pending.

The callback receives the same arguments passed to resolve() or reject(). That makes it easy to log context, though most cleanup code ignores those values.

💡
Beginner Tip

Think of always() as a finally block for promises: one place for work that must happen whether the async task succeeded or threw an error.

📝 Syntax

General form of deferred.always:

jQuery
deferred.always( alwaysCallback [, alwaysCallback ] )

Parameters

  • alwaysCallback — function executed when the Deferred is resolved or rejected. You may pass multiple functions; each is called in registration order.

Return value

  • Returns the same Deferred object, so you can chain .done(), .fail(), or another .always().

AJAX-style chain

jQuery
$.ajax({
  url: "/api/profile",
  method: "GET"
})
  .done(function (response) {
    renderProfile(response);
  })
  .fail(function (xhr, status, error) {
    showError(error);
  })
  .always(function () {
    hideSpinner();
  });

⚡ Quick Reference

GoalCode
Run on success or failuredfd.always(fn)
Success onlydfd.done(fn)
Failure onlydfd.fail(fn)
While pendingdfd.state() === "pending"
Multiple cleanup stepsChain several .always() calls

📋 always() vs done() / fail()

Each handler fires at a different stage of the Deferred lifecycle.

done()
on resolve

Success handlers only

fail()
on reject

Error handlers only

always()
on either

Shared cleanup

Order
done → always

done/fail run first

Examples Gallery

Each example uses jQuery’s Deferred API. Open DevTools or use the Try-it links to run them interactively.

📚 Getting Started

See always() fire after a successful resolve.

Example 1 — Cleanup After Resolve

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

jQuery
const 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

resolve("OK") triggers done first, then always. Both run synchronously in this example because no real network delay is involved.

Example 2 — Cleanup After Reject

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

jQuery
const 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

Without always(), you would duplicate spinner-hide logic in both done and fail. One always() handler covers both paths.

📈 Practical Patterns

Real-world AJAX-style chains and UI cleanup.

Example 3 — Classic done / fail / always Chain

Mirror the pattern used with $.ajax(): handle data, handle errors, then finalize.

jQuery
function fetchProfile() {
  const dfd = $.Deferred();

  // Simulate async work
  setTimeout(function () {
    if (Math.random() > 0.5) {
      dfd.resolve({ name: "Alex" });
    } else {
      dfd.reject("404 Not Found");
    }
  }, 300);

  return 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");
    });
}
Try It Yourself

How It Works

Outcome-specific UI updates live in done or fail. Shared UI state — buttons, overlays — belongs in always so it runs exactly once per request.

Example 4 — Hide a Loading Indicator

Show a spinner when the request starts; hide it in always() regardless of outcome.

jQuery
function loadItems() {
  $("#spinner").show();

  const dfd = $.Deferred();

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

  dfd
    .done(function (items) {
      $("#list").text(items.join(", "));
    })
    .fail(function () {
      $("#list").text("Could not load items.");
    })
    .always(function () {
      $("#spinner").hide();
    });
}
Try It Yourself

How It Works

Users should never see a spinner stuck on screen after a failed request. always() guarantees the UI resets.

Example 5 — Multiple always() Handlers

Register several cleanup callbacks; jQuery calls each in order when the Deferred settles.

jQuery
const 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

Splitting cleanup into small functions keeps each handler focused. Alternatively, call one function from a single always() callback if you prefer fewer registrations.

🚀 Use Cases

  • Cleanup tasks — close connections, release locks, or reset module state after async work completes.
  • Loading indicators — show spinners on start, hide them in always() so failures do not leave the UI stuck.
  • Logging and monitoring — record that a request finished, with timing metadata, independent of success.
  • UI updates — re-enable buttons, remove disabled classes, or restore focus after form submission.
  • Fallback preparation — pair with fail() for error messages while always() handles shared teardown.

🧠 How always() Fits the Deferred Lifecycle

1

Pending

Async work runs. always() callbacks are queued but not invoked yet.

Wait
2

Settled

Deferred resolves or rejects. Matching done() or fail() handlers run first.

Outcome
3

always() runs

Every registered always callback executes in order with resolve/reject arguments.

Cleanup
=

Consistent UI

Shared teardown runs once per operation — success or failure — without duplicated code.

📝 Notes

  • always() does not run while the Deferred is still pending.
  • Put outcome-specific logic in done() or fail(), not in always().
  • jqXHR from $.ajax() supports the same chaining methods as a Deferred.
  • Returning a new Deferred from an always() callback does not change the original Deferred’s state.
  • In greenfield code without jQuery, consider native Promise.prototype.finally() for the same pattern.

Browser Support

deferred.always() is part of jQuery’s Deferred implementation, available in jQuery 1.5+. It works wherever jQuery runs — including legacy browsers when you ship a supported jQuery build.

jQuery 1.5+

jQuery Deferred.always()

Supported in all jQuery 1.x, 2.x, and 3.x releases. Behavior is consistent across browsers because jQuery normalizes the Deferred API.

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

Bottom line: Safe in any project that already includes jQuery. For new apps without jQuery, use native Promises and finally() instead.

🎉 Conclusion

The deferred.always() method is the right tool when you need code to run after an asynchronous operation completes — whether it succeeded or failed. It keeps cleanup DRY and makes AJAX-driven UIs more reliable.

Practice the five examples above, then explore done() and fail() for outcome-specific handlers on the same Deferred chain.

💡 Best Practices

✅ Do

  • Hide spinners and re-enable buttons in always()
  • Keep always() callbacks focused on cleanup
  • Pair with fail() for user-facing error messages
  • Test both resolve and reject paths
  • Document why shared teardown lives in always()

❌ Don’t

  • Put success-only business logic in always()
  • Assume always() runs while still pending
  • Duplicate cleanup in done() and fail()
  • Trigger heavy side effects unrelated to teardown
  • Forget that arguments mirror resolve/reject values

Key Takeaways

Knowledge Unlocked

Five things to remember about always()

Reliable cleanup for jQuery async workflows.

5
Core concepts
02

Resolve

Runs after done

Success
03

Reject

Runs after fail

Error
🔄 04

Cleanup

Spinners, locks

Pattern
🔗 05

Chain

done → always

AJAX

❓ Frequently Asked Questions

always() registers a callback that runs once the Deferred settles — either resolved (success) or rejected (failure). 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, in the same order as other handlers for that event. It does not run while the Deferred is still pending.
Yes. jQuery passes the resolve or reject arguments to every always callback, matching whichever path the Deferred took.
Yes. jqXHR objects implement the Deferred interface, so you can chain .done(), .fail(), and .always() on AJAX requests — a common pattern for UI cleanup.
Conceptually similar: both run after success or failure. always() is jQuery-specific and integrates with the Deferred API; native finally() is the modern standard outside jQuery.
Yes. Each always callback you register is queued and executed in order when the Deferred resolves or rejects.
Did you know?

Before native Promise.finally() was widely available, jQuery’s always() was the go-to way to hide loading spinners after AJAX calls — one callback instead of duplicating cleanup in both success and error handlers.

Continue to catch()

Learn how jQuery handles rejected Deferreds with catch-style handlers.

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.

6 people found this page helpful