javascript - 并行运行promises但单独处理拒绝

时间:2016-08-21 14:43:17

标签: javascript promise bluebird

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

3 个答案:

答案 0 :(得分:3)

我会在地图中使用.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());

});

答案 1 :(得分:2)

  

我想知道是否有任何方法可以并行运行promises但是分别处理每个拒绝,并且不会使整个Promise失败。

确实有 - 只需使用catcherror处理它们:

const all = Promise.map(somethings, function(something) {
    return doSomething(something).catch(function(e) {
        return handleIt(e); // normal completion, no rejection or exception
    });
});

另请参阅Wait until all ES6 promises complete, even rejected promises

答案 2 :(得分:-1)

如果没有任何具有纯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})));