There's one more vital difference as of jQuery 3.0 that can easily lead to unexpected behaviour and isn't mentioned in previous answers:
Consider the following code:
let d = $.Deferred();_x000D_
d.done(() => console.log('then'));_x000D_
d.resolve();_x000D_
console.log('now');
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
_x000D_
this will output:
then
now
Now, replace done()
by then()
in the very same snippet:
var d = $.Deferred();_x000D_
d.then(() => console.log('then'));_x000D_
d.resolve();_x000D_
console.log('now');
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
_x000D_
output is now:
now
then
So, for immediatly resolved deferreds, the function passed to done()
will always be invoked in a synchronous manner, whereas any argument passed to then()
is invoked async.
This differs from prior jQuery versions where both callbacks get called synchronously, as mentioned in the upgrade guide:
Another behavior change required for Promises/A+ compliance is that Deferred .then() callbacks are always called asynchronously. Previously, if a .then() callback was added to a Deferred that was already resolved or rejected, the callback would run immediately and synchronously.