【问题标题】:Nodejs Promise.all not catching error/promise rejection when used with multiple map function calls与多个地图函数调用一起使用时,Nodejs Promise.all 未捕获错误/承诺拒绝
【发布时间】:2021-02-04 16:18:50
【问题描述】:

我正在使用 Promise.all 运行两个单独的函数,它们本身就是在 Promise.all 中多次运行函数的映射。

async function nonBlockingWithMapAndArray(): Promise<any> {
  let arr = [100,200,150];
  let arr2 = [500,1000,300]; // <--- value of 1000 causes an error to be thrown
  console.log(`nonBlockingWithMapAndArray: starting...`);
  const pa = await Promise.all([ 
    await iterateArrayAndCall(arr),
    await iterateArrayAndCall(arr2)    // <--- This throws an error
  ])
  .then( (data) => {
     console.log(`nonBlockingWithMapAndArray: In then...`);
  })
  .catch((err) => {     // <-- This should catch the error but does not, instead the error goes up to main which calls nonBlockingWithMapAndArray()
    console.log('nonBlockingWithMapAndArray: In catch', err);
  });

  console.log(`nonBlockingWithMapAndArray: Finished`);
  return pa;
}

当没有抛出错误时,我的解决方案可以正常工作。但是,如果抛出错误,Promise.all 的 catch 不会捕获错误,而是向上传播到主调用应用程序。

在此代码中,第二个函数调用iterateArrayAndCall(arr2) 会引发错误。但是Promise.all上的catch并没有捕捉到它。

任何帮助将不胜感激。完整代码如下...

bootstrap();

async function bootstrap() {
  let res;
  try {
    res = await nonBlockingWithMapAndArray();
  } catch (err) {
    console.log('Main: In catch');   // <-- This is where the error is caught
  }
}

async function nonBlockingWithMapAndArray(): Promise<any> {
  let arr = [100,200,150];
  let arr2 = [500,1000,300]; // <--- value of 1000 throws an error
  console.log(`nonBlockingWithMapAndArray: starting...`);
  const pa = await Promise.all([ 
    await iterateArrayAndCall(arr),
    await iterateArrayAndCall(arr2)    // <--- This throws an error
  ])
  .then( (data) => {
     console.log(`nonBlockingWithMapAndArray: In then...`);
  })
  .catch((err) => {     // <-- This should catch the error but does not
    console.log('nonBlockingWithMapAndArray: In catch', err);
  });

  console.log(`nonBlockingWithMapAndArray: Finished`);
  return pa;
}

async function iterateArrayAndCall(arr: any) : Promise<any> {
  return await Promise.all(
    arr.map( async (element) => {
      await delayAndGetRandomPromWithError(element); //If element is 1000 an error will be generated
    })
  )
  .then((data) => {
     console.log(`iterateArrayAndCall: in then...`);
  })
  .catch((err) => {
    console.log(`iterateArrayAndCall: in catch`);
    throw new Error('Failed in iterateArrayAndCall');
    // Also tried:
    // return Promise.reject();
    // return err
  });

}

async function delayAndGetRandomPromWithError(ms): Promise<number> {
  console.log(`MS start :${ms}`);

  if( ms === 1000 ) {
    throw new Error('1000 so throw error...');
  }

  const p: Promise<number> = new Promise(resolve => 
    setTimeout(() => {
      const val: number = Math.trunc(Math.random() * 100);
      console.log(`MS finish :${ms}`);
      resolve(val);
    }, ms
  ));
  return p;
};

async function throwOne() {
  console.log(`Am I blocking?`);
  throw new Error(`Test error`);
}

运行时输出


nonBlockingWithMapAndArray: starting...
MS start :100
MS start :200
MS start :150
MS finish :100
MS finish :150
MS finish :200
iterateArrayAndCall: in then...
MS start :500
MS start :1000
MS start :300
iterateArrayAndCall: in catch
Main: In catch   <--- I expect to see this here instead .... 'nonBlockingWithMapAndArray: In catch'
MS finish :300
MS finish :500

【问题讨论】:

  • 您正在等待承诺,然后尝试将 result 放入您传递给 Promise.all 的数组中...
  • 嗨,乔恩,感谢您的反馈。使用我尝试过的三种解决方案之一,iterateArrayAndCall 中的return err 将错误放入返回值中。现在的问题是没有抛出错误,iterateArrayAndCall 中的 Promise.All 解析,thennonBlockingWithMapAndArray 中被调用,而不是 catch。

标签: node.js async-await promise promise.all


【解决方案1】:

可能您的iterateArrayAndCall 直接在其自己的堆栈(而不是异步堆栈)上抛出,因此错误被其底层堆栈(nonBlockingWithMapAndArray)捕获:

function iterateArrayAndCall () { throw Error() }

Buf 如果你将调用包装成一个promise,它将被.catch 块捕获:

function iterateArrayAndCall () { 
  return new Promise((resolve, reject) => { throw Error() })
}

【讨论】:

  • 感谢您的意见 clarkttfu。我试过了,它和throw new Error('Failed in iterateArrayAndCall'); 的效果一样......即主函数捕获它
猜你喜欢
  • 1970-01-01
  • 2022-11-11
  • 2020-06-06
  • 2022-12-04
  • 2017-06-19
  • 1970-01-01
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多