Promise.all包装器可以捕获错误

时间:2018-05-07 21:02:58

标签: javascript node.js ecmascript-6 es6-promise

我在一个简单的脚本中逐字记录:

Promise.all(links.map(function (l) {
  return Promise.resolve(require(l).r2gSmokeTest())
     .then((v:any) => ({path: l, result: v}));
}))
.then(function(results){

})
.catch(function(e){

}):

问题是,如果require()调用因任何原因抛出错误,则承诺链不会抓住它。

是最简单的方法,可以避免将Promise.all包装在一个函数中,如下所示:

const getAllPromises = function(links){
   return Promise.resolve(null).then(function(){
       return Promise.all(links.map(function (l) {
         return Promise.resolve(require(l).r2gSmokeTest())
         .then((v:any) => ({path: l, result: v}));
}));

在我看来,也许Promise.all应该有一个不同的API,如:

Promise.all(function(){
   return values.map(v => whatever);
});

如果在Promise链中没有调用Promise.all,那么任何错误都会被捕获......

2 个答案:

答案 0 :(得分:2)

使用不能抛出的async function - 它只会在发生异常时返回被拒绝的承诺:

Promise.all(links.map(async function (l) {
  const v: any = await require(l).r2gSmokeTest();
  return {path: l, result: v};
}))

通常,对任何执行异步操作的函数的期望是始终返回promise和never throw synchronously。如果有必要,您的map回调应该遵守该问题,并在try … catch (e) { return Promise.reject(e); }电话周围require。您也可以考虑使用类似Bluebird's Promise.try的帮助函数。

答案 1 :(得分:2)

您的require()发生在Promise上下文之外的地图级别上,这就是为什么它会立即传播到全局级别,所以如果您只是将其包装到new Promise它应该按预期处理错误:

Promise.all(links.map(function(l) {
    return new Promise(resolve => resolve(require(l).r2gSmokeTest())) // <-- here
      .then((v: any) => ({
        path: l,
        result: v
      }));
  }))
  .then(function(results) {

  })
  .catch(function(e) {

  }):