javascript - 运行 并行承诺但分别处理拒绝

javascript - run promises in parallel but handle rejections separately

我使用 bluebird.js map 函数对我使用的外部 API 执行并行请求。
每当任何内部承诺被拒绝时,map 函数也会被拒绝(我知道这是设计使然)。
我想知道是否有任何方法可以并行 运行 promises 但分别处理每个拒绝,而不会使整个 Promise 失败。

I was wondering if there is any way to run promises in parallel but handle each rejection separately, and not fail the entire Promise.

当然有 - 只需使用 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
    });
});

另见 一般情况。

我会使用 .reflect 和地图来获得承诺检查结果:

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());

});

如果没有任何具有纯 ES6 承诺的库,您可能会有这样的方法。在这种情况下,promiseAll 函数将兑现已解决的承诺以及被拒绝的承诺。

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})));