【问题标题】:Promise.all wrapper which can trap errorsPromise.all 可以捕获错误的包装器
【发布时间】:2018-05-07 21:02:58
【问题描述】:

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

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 链都不会捕获它。

避免这种情况的最简单方法是将 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.all 没有在 Promise 链中调用,任何错误都可以被捕获......

【问题讨论】:

  • 你的问题到底是什么?
  • @Bergi 好像你已经明白了,抱歉没那么清楚

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


【解决方案1】:

使用不能抛出的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 的辅助函数。

【讨论】:

  • hmmm,但是如果您在这种情况下执行 Promise.all().then(),如果在 async 函数中引发错误,then 是否会捕获承诺?我不确定它是否会
  • 好的,我测试过,这可行,赞成,但我不确定为什么。如果你能解释更多为什么它会很好
【解决方案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) {

  }):

【讨论】:

  • 我认为使用Promise.resolve(null) 进行包装比使用执行器创建新的Promise 更简单?
  • @Olegzandr 好吧,这取决于“简单”的定义,我认为“简单”意味着通过尽可能少地更改源来解决问题。如果你的不同,请澄清这一点。请记住Promise.resolve(arg)new Promise(resolve =&gt; resolve(arg)) 的别名,每个.then 都在链中创建一个新的promise 对象。这就是为什么在某种意义上调用new Promise() 更简单,因为您不必创建额外的承诺,也不必输入像null 这样的神奇占位符值。
猜你喜欢
  • 2019-01-21
  • 2021-09-08
  • 2018-05-14
  • 2019-01-27
  • 2012-01-11
  • 2011-06-18
  • 2022-06-15
  • 2020-01-29
相关资源
最近更新 更多