30

Seems to me that both does the same thing.

Docs:

Niyaz
  • 53,943
  • 55
  • 151
  • 182

4 Answers4

35

It would seem that deferred.then() allows you to pass two separate callbacks for success and failure, whereas deferred.always() takes n number of callbacks which will all be called regardless of the outcome of the initial event.

I would say use deferred.always() in the cases where success/failure of the initial event are not important

JamesHalsall
  • 13,224
  • 4
  • 41
  • 66
  • 17
    Also, `.then(fn1, fn2)` can be considered a shorthand for `.done(fn1).fail(fn2)`. – Fabrício Matté Sep 16 '12 at 15:35
  • 2
    Wow Thanks. Stupid me. I was staring a the docs for some time now and did not notice the difference. – Niyaz Sep 16 '12 at 15:37
  • Note @Ignitor's answer below, which references the fact that `deferred.then()` callbacks can return _new_ promise objects for further asynchronous processing (what `deferred.pipe()` used to do). Ex: `deferred.then(function() { return someNewDeferredThing; }, function() { return null; });` -- In that case, the done callback will result in tracking the status of a new promise object, while the result of the fail callback will be to keep the original deferred object's status (rejected in this case). – Soulriser Dec 22 '16 at 19:44
7

With .then() you can provide an individual callback for when the $.Deferred is resolved (done), and another for when the $.Deferred is rejected (fail).

.always(), on the other hand, allows you to provide a callback that always gets executed, whether the $.Deferred has been resolved or rejected. In other words, within this callback, it doesn't matter if the AJAX call has failed or has been been successfully executed.

I tend to put code in .always() when I want that code to run everytime, and independently of whether the $.Deferred was resolved successfully or not. For example, to clear an AJAX loading indicator or to hide a progress bar. Using .then() you'd have something like this:

$.get("/some/url").then(function () { // done callback
  $(".progress-bar").hide();
}, function () { // fail callback
  $(".progress-bar").hide();
});

Whilst if you used .always(), you'd just need a single callback, because you always want to hide the progress bar, no matter if the $.Deferred was resolved or rejected:

$.get("/some/url").always(function () {
  $(".progress-bar").hide();
});
João Silva
  • 89,303
  • 29
  • 152
  • 158
6

Prior to jQuery 1.8: .always(fn) is equivalent to .then(fn, fn)

As of jQuery 1.8: .always(fn) is similar to .then(fn, fn) but it differs in what is returned (see http://api.jquery.com/deferred.then/ for details)

Ignitor
  • 2,907
  • 33
  • 50
0

The big benefit of then (as of 1.8) is the capability to chain tasks explicitly because it returns a promise which will be resolved with the result of the callback(s)

Example from documentation:

var request = $.ajax( url, { dataType: "json" } ),
    chained = request.then(function( data ) {
      return $.ajax( url2, { data: { user: data.userId } } );
    });

chained.done(function( data ) {
  // data retrieved from url2 as provided by the first request
});
schlamar
  • 9,238
  • 3
  • 38
  • 76