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?

Was it helpful?

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 .thenable 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 .thenable 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top