Read more

jQuery promises: done() and then() are not the same

Henning Koch
April 15, 2016Software engineer at makandra GmbH

jQuery's deferred Show archive.org snapshot objects behave somewhat like standard promises Show archive.org snapshot , but not really.

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

One of many subtle differences is that there are two ways to chain callbacks to an async functions.

The first one is done, which only exists in jQuery:

$.ajax('/foo').done(function(html) {
  console.debug("The server responded with %s", html);
});

There is also then, which all promise libraries have:

$.ajax('/foo').then(function(html) {
  console.debug("The server responded with %s", html);
});

However, .done() and .then() do not behave the same. In particular, if a standard promise callback returns another promise, this will delay the resolution of all later promises. jQuery's then behaves like this, but done does not. It is not possible for a done callback to delay the resolution of later callbacks.

Always prefer .then() so your code is compatible with the open promise standard ( Promises/A+ Show archive.org snapshot ).

Example

We want to request /foo and, as soon as we have the response, make a second request to /bar:

var promise = $.ajax('/foo').done(function() {
  return $.ajax('/bar');
});

Quiz: When does promise resolve?

Well, if you use done, it will resolve as soon as we have the response to /foo:

var promise = $.ajax('/foo').done(function() {
  return $.ajax('/bar'); // Returning does not actually do anything here.
});

promise.then(function() {
  console.debug("We have the response to /foo, but /bar is still loading");
});

If we use then instead, it will only resolve once we have responses to both /foo and /bar:

var promise = $.ajax('/foo').then(function() {
  return $.ajax('/bar');
});

promise.then(function() {
  console.debug("We have the responses to both /foo and /bar");
});

Enjoy.

Posted by Henning Koch to makandra dev (2016-04-15 14:38)