I have used $q (Angular.js) and would often return promises within a .then
call. The effect was that the next .then
call would wait for the previous promise to finish.
I am now using native es6 promises to try to 'promisify' a callback based library and I am unable to do so.
The problem is that the next value in the .then
chain is a promise object, rather than the resolved value of that promise. It calls the next .then
value before the promise is resolved, simply returning the last return value.
Is there anyway to wait for the previous promise to resolve?
Example:
$.ajax({
url: "//localhost:3000/api/tokens",
type: "POST",
data: JSON.stringify({
user: {
email: '[email protected]',
password: 'password123'
}
}),
contentType: "application/json"
})
.then(data => data.token.encoded) // OK
.then(token => Farmbot({ token: token })) // OK
.then(function(bot){ // OK
return new Promise(function(resolve, reject) {
bot.connect(function(){ resolve(bot); });
});
}, errorr)
.then(function(bot){ // NOT OK!
// passes in an unresolved promise object, which is useless.
//
bot; // => {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
});
My question is:
Do ES6 promises wait for the previous .then
's promise to resolve?
The issue stems from trying to use a native Promise
within a chain of Deferred
promises.
Currently (jQuery 1.8 – 2.x), jQuery's definition of .then()
only recognizes the library's own type in its support for chaining.
So, you could return a $.Deferred()
promise instead:
// ...
.then(function(bot){
return $.Deferred(function(defer) {
bot.connect(function(){ defer.resolve(bot); });
});
}, errorr)
// ...
Or, you can use Promise.resolve(thenable)
to convert the initial $.Deferred()
given by $.ajax()
to a native Promise
so that you're using the native .then()
throughout the chain, which will recognize a new Promise()
being returned (as well as a $.Deferred()
):
Promise.resolve($.ajax({
// ...
}))
.then(data => data.token.encoded)
// ...
Or, you can try jQuery 3.0, currently in beta:
jQuery.Deferred is now Promises/A+ compatible
jQuery.Deferred objects have been updated for compatibility with Promises/A+ and ES2015 Promises, verified with the Promises/A+ Compliance Test Suite. [...]
With it, your original snippet should work as you expected without any revision.
Do ES6 promises wait for the previous .then's promise to resolve?
Put it this way: an ES6 promise never, ever calls a .then(onFulfilled)
function with a promise or thenable object. Onfulfilled listeners are only called with non-promise values.
Converting jQuery "thenable" objects into ES6 Promises before trusting them may solve the problem:
var jqPromise = $.ajax({
url: "//localhost:3000/api/tokens",
type: "POST",
data: JSON.stringify({
user: {
email: '[email protected]',
password: 'password123'
}
}),
contentType: "application/json"
})
.then(data => data.token.encoded) // OK
.then(token => Farmbot({ token: token })) // OK
;
var es6Promise = Promise.resolve(jqPromise); // convert to ES6 promise
es6Promise.then(function(bot){ // OK
return new Promise(function(resolve, reject) {
bot.connect(function(){ resolve(bot); });
});
}, errorr)
.then(function(bot){ // will not pass in unfulfilled promise
// process bot value
});
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