I've been reading about jQuery deferreds and promises and I can't see the difference between using .then()
& .done()
for successful callbacks. I know Eric Hynds mentions that .done()
and .success()
map to the same functionality but I'm guessing so does .then()
as all the callbacks are all invoked on a completion of a successful operation.
Can anyone please enlighten me to the correct usage?
done() method in jQuery is used to add handlers which are to be called when the deferred object is resolved. Parameters: Callbacks: This parameter specifies a function, or array of functions, which are called when the Deferred is resolved.
A few promise libraries have a . done() method whose main purpose is to catch and rethrow any errors that were not handled, so that they show up in the console (in browsers) or crash the process in Node.
If you are creating a Deferred, keep a reference to the Deferred so that it can be resolved or rejected at some point. Return only the Promise object via deferred. promise() so other code can register callbacks or inspect the current state. For more information, see the documentation for Deferred object.
A promise is, as the name says, a promise about a future value. Together with the Promise object , Deferred represents the jQuery implementation of promises. You can attach callbacks to it to get that value. It possesses a subset of the methods of the Deferred object : always(), done(), fail(), state(), and then().
The callbacks attached to done()
will be fired when the deferred is resolved. The callbacks attached to fail()
will be fired when the deferred is rejected.
Prior to jQuery 1.8, then()
was just syntactic sugar:
promise.then( doneCallback, failCallback ) // was equivalent to promise.done( doneCallback ).fail( failCallback )
As of 1.8, then()
is an alias for pipe()
and returns a new promise, see here for more information on pipe()
.
success()
and error()
are only available on the jqXHR
object returned by a call to ajax()
. They are simple aliases for done()
and fail()
respectively:
jqXHR.done === jqXHR.success jqXHR.fail === jqXHR.error
Also, done()
is not limited to a single callback and will filter out non-functions (though there is a bug with strings in version 1.8 that should be fixed in 1.8.1):
// this will add fn1 to 7 to the deferred's internal callback list // (true, 56 and "omg" will be ignored) promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 );
Same goes for fail()
.
There is also difference in way that return results are processed (its called chaining, done
doesn't chain while then
produces call chains)
promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return 123; }).then(function (x){ console.log(x); }).then(function (x){ console.log(x) })
The following results will get logged:
abc 123 undefined
While
promise.done(function (x) { // Suppose promise returns "abc" console.log(x); return 123; }).done(function (x){ console.log(x); }).done(function (x){ console.log(x) })
will get the following:
abc abc abc
---------- Update:
Btw. I forgot to mention, if you return a Promise instead of atomic type value, the outer promise will wait until inner promise resolves:
promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return $http.get('/some/data').then(function (result) { console.log(result); // suppose result === "xyz" return result; }); }).then(function (result){ console.log(result); // result === xyz }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then })
in this way it becomes very straightforward to compose parallel or sequential asynchronous operations such as:
// Parallel http requests promise.then(function (x) { // Suppose promise returns "abc" console.log(x); var promise1 = $http.get('/some/data?value=xyz').then(function (result) { console.log(result); // suppose result === "xyz" return result; }); var promise2 = $http.get('/some/data?value=uvm').then(function (result) { console.log(result); // suppose result === "uvm" return result; }); return promise1.then(function (result1) { return promise2.then(function (result2) { return { result1: result1, result2: result2; } }); }); }).then(function (result){ console.log(result); // result === { result1: 'xyz', result2: 'uvm' } }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then })
The above code issues two http requests in parallel thus making the requests complete sooner, while below those http requests are being run sequentially thus reducing server load
// Sequential http requests promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return $http.get('/some/data?value=xyz').then(function (result1) { console.log(result1); // suppose result1 === "xyz" return $http.get('/some/data?value=uvm').then(function (result2) { console.log(result2); // suppose result2 === "uvm" return { result1: result1, result2: result2; }; }); }); }).then(function (result){ console.log(result); // result === { result1: 'xyz', result2: 'uvm' } }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With