jQuery Deferred, Promises and $.when()

Some tasks take time: Ajax requests, animations, timers. A promise is an object which represents the result of such a task, which will come later. jQuery has used promises for many years, in Ajax and in animations, and it has its own object $.Deferred.

Ajax methods return promises

You already used this in the Ajax chapter: .done() runs on success and .fail() on error.

{ "name": "File A" }
{ "name": "File B" }
<p>Page</p>

$.when(): wait for many tasks

$.when() waits for all the given promises, and then runs .done() with all the results.

var a = $.getJSON('a.json');
var b = $.getJSON('b.json');

$.when(a, b).done(function (resA, resB) {
  console.log('A: ' + resA[0].name);
  console.log('B: ' + resB[0].name);
  console.log('Both requests are complete');
});
Console output

A: File A
B: File B
Both requests are complete

For Ajax requests, each result is an array: [data, status, jqXHR], so we read resA[0] for the data.

Create your own with $.Deferred()

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

wait(30).done(function (msg) { console.log(msg); });

$.when(wait(20), wait(40)).done(function (m1, m2) {
  console.log(m1 + ' and ' + m2);
});
Console output

waited 30 ms
waited 20 ms and waited 40 ms

  • d.resolve(value) says the task is successful.
  • d.reject(reason) says the task failed.
  • d.promise() gives a read-only version to return to other code.

Reject and fail

function check(n) {
  var d = $.Deferred();
  if (n > 0) d.resolve('OK ' + n); else d.reject('n must be positive');
  return d.promise();
}

check(5).done(function (v) { console.log(v); });
check(-1).fail(function (e) { console.log('Error: ' + e); });
Console output

OK 5
Error: n must be positive

then() and chaining

$.getJSON('a.json')
  .then(function (data) {
    console.log('First: ' + data.name);
    return $.getJSON('b.json');       // return another promise to continue
  })
  .then(function (data) {
    console.log('Second: ' + data.name);
  })
  .catch(function () {
    console.log('A request failed');
  });
Console output

First: File A
Second: File B

jQuery promises and native Promises

Since jQuery 3, the promises follow the Promises/A+ standard, so .then() works like the native one, and you can use them with async and await:

async function load() {
  var a = await $.getJSON('a.json');
  var b = await $.getJSON('b.json');
  console.log(a.name + ' + ' + b.name);
}
load();
Console output

File A + File B

For new code, many people prefer the native fetch() and Promise.all(). The jQuery slim build (without Ajax and effects) does not include Deferred. See jQuery vs Vanilla JavaScript.

Note: Always add an error handler (.fail() or .catch()), or the failures stay silent. Next: jQuery vs Vanilla JavaScript.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.