Promise.all() doesn't guarantee that promises will be resolved in order. How can this be done?
How can I sequentially chain promises using bluebirdjs?
Since you're using Bluebird JS, this can be actually done in a simple way.
In version 2.0, Bluebird introduced the Promise.each
method that does this, for looping a then is simple enough, but since it is so common and got requested time after time eventually it was added as its own method.
function foo(item, ms){ // note bluebird has a delay method
return Promise.delay(ms, item).then(console.log.bind(console))
}
var items = ['one', 'two', 'three'];
Promise.each(items, function(item, i){
return foo(item, (items.length - i) * 1000)
});
Which produces the same result as the other answer, only with less lines of code and it also lets Bluebird perform optimizations on the iteration.
The thing that confused me most is that the async function being chained needs to return a function that returns a promise. Here's an example:
function setTimeoutPromise(ms) {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
function foo(item, ms) {
return function() {
return setTimeoutPromise(ms).then(function () {
console.log(item);
});
};
}
var items = ['one', 'two', 'three'];
function bar() {
var chain = Promise.resolve();
items.forEach(function (el, i) {
chain = chain.then(foo(el, (items.length - i)*1000));
});
return chain;
}
bar().then(function () {
console.log('done');
});
Notice that foo returns a function that returns a promise. foo() does not return a promise directly.
See this Live Demo
Benjamin's example is definitely simpler. I developed mine as I was dealing with the lie promise lib (github.com/calvinmetcalf/lie) in pouchdb in which case there isn't support for the each() call. My question should really have referenced liejs and not bluebirdjs :). –
Pinochle
@BenjaminGruenbaum how else would you chain these promises using my code? I'm still learning the nuances of promises, so I'd appreciate your input. –
Pinochle
return chain
instead of return chain.then()
–
Quiescent Yup, missed that one :) –
Pinochle
Also,
for .. in
loops do not guarantee iteration order, this can be result in an incorrect order in your case, you can use items.forEach
or for(var i = 0;...
instead –
Quiescent © 2022 - 2024 — McMap. All rights reserved.
chain.then()
whenthen()
is called like that it effectively doesn't do anything but copy the promise. – Quiescent