ECMAScript Promise.all method works with jQuery.Deferred. Why?
-
22-12-2019 - |
Question
I was making a research for Promises in JavaScript. I'm was interesting can I combine ECMAScript Promises with other implementations, for example jQuery $.Deferred
. And I was surprised when Promises.all
works fine with jQuery $.Deferred
. I'm trying to find the answer in jQuery source code and CommonJS Promises/A specs, but I still misunderstood why this code works as I expected(do console.log
after 10 seconds, not 5 seconds):
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();//resolve first promise after 5 secs
console.log('Promise resolved');
}, 5000);
});
var deferred = $.Deferred();
setTimeout(function () {
deferred.resolve();//resolve after 10 seconds
console.log('Deferred resolved');
}, 10000);
Promise.all([promise,deferred]).then(function () {
console.log('All is done');//log after 10 seconds
});
Do you have any ideas?
Promise.all
must rely on something field or method of $.Deferred
to understand is resolved it or not. What is that method/field?
Solution
The promises A+ specification (on which the promises unwrapping specification was based on which native promises use) was specifically built to do this.
With a design goal of libraries inter-oping well, the specification is built around a single method: .then
.
The then method specifies how a continuation of a promise works. jQuery promises expose .then
since version 1.8 which means they try to participate in this game. While jQuery deferreds and promises are not Promises/A+ promises - they attempt to be Promises/A promises which means the following:
return Promise.resolve($.get(...))
Will always work. A+ promises (and native promises) will assimilate every .then
able recursively and resolve with its value when you return it.
Promise.resolve({then:function(fn){ return fn(3); }}).then(function(el){
console.log(el); // this logs 3
})
If we check the specification , we can see:
Let result be Invoke(nextPromise,
"then"
, (resolveElement, promiseCapability.[[Reject]])).
(also related is this)
Which calls .then
and resolves the next item when that .then
able resolves
jQuery's deferred uses a nonstandard promise implementation so it cannot consume native promises (That is, you can't predictably $.when
a native promise. The other way around works.