I saw this example implementation of Promise.all - which runs all promises in parallel - Implementing Promise.all
Note that the functionality I am looking for is akin to Bluebird's Promise.mapSeries http://bluebirdjs.com/docs/api/mapseries.html
I am making an attempt at creating Promise.series, I have this which seems to work as intended (it actually is totally wrong, don't use it, see answers):
Promise.series = function series(promises){
return new Promise(function(resolve,reject){
const ret = Promise.resolve(null);
const results = [];
promises.forEach(function(p,i){
ret.then(function(){
return p.then(function(val){
results[i] = val;
});
});
});
ret.then(function(){
resolve(results);
},
function(e){
reject(e);
});
});
}
Promise.series([
new Promise(function(resolve){
resolve('a');
}),
new Promise(function(resolve){
resolve('b');
})
]).then(function(val){
console.log(val);
}).catch(function(e){
console.error(e.stack);
});
However, one potential problem with this implementation is that if I reject a promise, it doesn't seem to catch it:
Promise.series([
new Promise(function(resolve, reject){
reject('a'); // << we reject here
}),
new Promise(function(resolve){
resolve('b');
})
]).then(function(val){
console.log(val);
}).catch(function(e){
console.error(e.stack);
});
does anyone know why the error doesn't get caught and if there is a way to fix this with Promises?
According to a comment, I made this change:
Promise.series = function series(promises){
return new Promise(function(resolve,reject){
const ret = Promise.resolve(null);
const results = [];
promises.forEach(function(p,i){
ret.then(function(){
return p.then(function(val){
results[i] = val;
},
function(r){
console.log('rejected');
reject(r); // << we handle rejected promises here
});
});
});
ret.then(function(){
resolve(results);
},
function(e){
reject(e);
});
});
}
but this still doesn't work as expected...
The promise returned by then
in the forEach
loop does not handle potential errors.
As pointed out in a comment by @slezica, try to use reduce
rather than forEach
, this chains all promises together.
Promise.series = function series(promises) {
const ret = Promise.resolve(null);
const results = [];
return promises.reduce(function(result, promise, index) {
return result.then(function() {
return promise.then(function(val) {
results[index] = val;
});
});
}, ret).then(function() {
return results;
});
}
Keep in mind that the promises are already "running" at that point though. If you truly want to run your promises in series, you should adjust your function and pass in an array of functions that return promises. Something like this:
Promise.series = function series(providers) {
const ret = Promise.resolve(null);
const results = [];
return providers.reduce(function(result, provider, index) {
return result.then(function() {
return provider().then(function(val) {
results[index] = val;
});
});
}, ret).then(function() {
return results;
});
}
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