Reputation: 324
The following Promise
behaves as expected, the Promise
in the return
statement gets fulfilled and the then
right afterwards gets executed before the last call of then:
(new Promise(resolve => resolve(true)))
.then(function(){
console.log(0);
return new Promise(resolve => setTimeout(resolve, 1000))
.then(function() {
console.log(1);
});
}).then(function() {
console.log(2);
});
The result is
0
1
2
But when the first Promise
is a jQuery Promise
like in the following case
$.post("index.php")
.then(function() {
console.log(0);
return new Promise(resolve => setTimeout(resolve, 1000))
.then(function() {
console.log(1);
});
}).then(function() {
console.log(2);
});
the result is
0 2 1
which indicates, that the second Promise
is not passed on as in standard JavaScript promises.
Is there a way to force the standard behavior?
I'm using jQuery 2.0.0.
Upvotes: 2
Views: 70
Reputation: 664920
jQuery 2 does not support Promises/A+, and cannot assimilate promises from other implementations ("thenables"). The native promise that is returned from the callback and resolves the outer promise is not being awaited, but rather used as the immediate fulfillment value. You can see this by inspecting the argument passed to your final callback.
Is there a way to force the standard behavior?
See How to dodge jQuery promises completely when chaining two async jQuery functions?
Basically just wrap the $.post("index.php")
that starts your chain in Promise.resolve
to get a native promise with all its glory (and expected behavior).
The other way round (wrapping the native promise from the timeout in a jQuery promise) I can really not recommend, but it would basically come down to
return $.Deferred(def => promise.then(def.resolve, def.reject)).promise()
Upvotes: 5
Reputation: 471
jQuery(the version you use) maybe doesn't work with the es6 promises, I think they work with something called "defer object", because of that doesn't work.
The great Kyle Simpson, in his book "You don't know Js: Async and performance" writes about promises, this can help you:
"As of ES6, there's a new concept layered on top of the event loop queue, called the "Job queue." The most likely exposure you'll have to it is with the asynchronous behavior of Promises (see Chapter 3)."
Because of that "new concept layered", it is not possible for your jquery version to works well mixing "fake" promises with standard promises.
Trying to overwrite your $.post with:
Promise.resolve($.post("index.php"))
.then(function() {
console.log(0);
return new Promise(resolve => setTimeout(resolve, 1000))
.then(function() {
console.log(1);
});
}).then(function() {
console.log(2);
});
Now your chain of promises are all es6 standard.
The link to Kyle Simpson book:
You Don't Know JS: Async & Performance
And a link to see all the You Don't Know JS series book:
Upvotes: 1