Deferred, Promises & $.when

Coordinate asynchronous work with jQuery's Deferred objects and $.when.

Long before async/await, jQuery gave us a way to represent “a value that isn't ready yet”: the Deferred. A Deferred is a producer — you resolve() or reject() it. Its promise is the read-only consumer side that others attach .then() callbacks to.

Making your own Deferred

function wait(ms) {
  var d = $.Deferred();
  setTimeout(function () { d.resolve("done after " + ms + "ms"); }, ms);
  return d.promise();
}

wait(500).then(function (msg) {
  console.log(msg);
});

$.when — wait for several things at once

Every $.ajax() call already returns a promise, so you rarely build Deferreds by hand. Where they shine is combining asynchronous work. $.when resolves once all of its arguments have resolved:

$.when(
  $.getJSON("/user.json"),
  $.getJSON("/settings.json")
).done(function (userResult, settingsResult) {
  // each argument is [ data, statusText, jqXHR ]
  console.log(userResult[0], settingsResult[0]);
}).fail(function () {
  console.log("at least one request failed");
});
jQuery 3 realigned Deferreds to be Promises/A+ compliant. In modern code you can hand a jQuery promise straight to awaitawait $.getJSON(url) just works.

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A dashboard waits for three parallel API calls to finish before rendering the combined report, using $.when().
  • A wizard step validates a field asynchronously via AJAX and returns a Deferred so the next-step logic can await the result.
  • A media player pre-loads audio and metadata in parallel and chains $.when() to start playback only when both are ready.

More examples

Wait for two parallel $.ajax calls

$.when() accepts multiple jqXHR Deferreds and calls .done() only when ALL of them have resolved.

Example Β· html
<button id="load">Load dashboard</button>
<p id="out"></p>
<script>
$(function () {
  $("#load").click(function () {
    var reqA = $.get("/api/stats");
    var reqB = $.get("/api/alerts");
    $.when(reqA, reqB).done(function (resA, resB) {
      var stats  = resA[0];
      var alerts = resB[0];
      $("#out").text("Stats: " + stats.count + "  Alerts: " + alerts.count);
    });
  });
});
</script>

Create and resolve a custom Deferred

$.Deferred() creates a manual promise; .resolve() triggers .done() and .reject() triggers .fail() consumers.

Example Β· html
<button id="run">Run async task</button>
<p id="status"></p>
<script>
function asyncValidate(value) {
  var dfd = $.Deferred();
  setTimeout(function () {
    if (value.length >= 3) dfd.resolve("Valid: " + value);
    else dfd.reject("Too short");
  }, 500);
  return dfd.promise();
}

$(function () {
  $("#run").click(function () {
    asyncValidate("Alice")
      .done(function (msg) { $("#status").text(msg); })
      .fail(function (err) { $("#status").text("Error: " + err); });
  });
});
</script>

Chain Deferreds with .then()

Returning a new Deferred from .then() chains dependent requests sequentially without deeply nesting callbacks.

Example Β· html
<button id="chain">Run chain</button>
<p id="log"></p>
<script>
$(function () {
  $("#chain").click(function () {
    $.get("/api/user/1")
      .then(function (user) {
        return $.get("/api/orders?userId=" + user.id);
      })
      .then(function (orders) {
        $("#log").text("Orders: " + orders.length);
      })
      .fail(function () {
        $("#log").text("Request failed.");
      });
  });
});
</script>

Discussion

  • Be the first to comment on this lesson.
Deferred, Promises & $.when β€” jQuery | SoundsCode