Reputation: 1077
I use bluebird.js
map
function to perform parallel requests to an external API I use.
whenever any of the inner promises gets rejected, the map
function also gets rejected (I know that this is by design).
I was wondering if there is any way to run promises in parallel but handle each rejection separately, and not fail the entire Promise.
Upvotes: 0
Views: 281
Reputation: 26161
Without any library with pure ES6 promises you may have an approach like this. In this case the promiseAll
function would honor resolved promises along with the rejected ones.
function promisify(fun){
return (data) => new Promise((resolve,reject) => fun(data, (err,res) => err ? reject(err) : resolve(res)));
}
function async(data, callback){
data.val+= " msec";
Math.random() < 0.5 ? setTimeout(_ => callback(false,data.val),data.dur)
: setTimeout(_ => callback("error"),data.dur);
}
function myNormalCallback(resultObject){
console.log("Promise " + resultObject.count + " returned " + resultObject.result);
}
function myErrorCallback(errorObject){
console.log("Promise " + errorObject.count + " returned " + errorObject.error);
}
function promiseAll(proms){
return new Promise((v,x) => { var results = new Array(proms.length).fill(void 0);
proms = proms.map((prom,i) => prom.then(res => {results[i] = res;
results.indexOf(void 0) === -1 && v(results);
})
.catch(err => {results[i] = err;
results.indexOf(void 0) === -1 && v(results);
}));
});
}
var datas = [{val: 100, dur: 1000},{val: 200, dur: 2000},{val: 300, dur: 3000}],
proms = datas.map(data => promisify(async)(data));
promiseAll(proms).then(results => results.map((res,i) => res === "error" ? myErrorCallback({count:i,error: res})
: myNormalCallback({count:i,result: res})));
Upvotes: -1
Reputation: 664548
I was wondering if there is any way to run promises in parallel but handle each rejection separately, and not fail the entire Promise.
Sure there is - just handle them using catch
or error
:
const all = Promise.map(somethings, function(something) {
return doSomething(something).catch(function(e) {
return handleIt(e); // normal completion, no rejection or exception
});
});
See also Wait until all ES6 promises complete, even rejected promises in general.
Upvotes: 2
Reputation: 276306
I would use .reflect
with the map to get promise inspections as the result:
const all = Promise.map(items, item => doSomething(item).reflect());
all.then(items => {
// will contain an array of the promises that fulfilled correctly
let fulfilled = items.filter(x => x.isFulfilled()).map(x => x.value()));
// will contain an array of the promises that rejected
// so you can handle the errors
let rejected = items.filter(x => x.isRejected()).map(x => x.reason());
});
Upvotes: 3