Promise.all 中无法捕获的异常

Uncatchable exception in Promise.all

提问人:Poyoman 提问时间:4/18/2023 更新时间:4/18/2023 访问量:104

问:

我在浏览器中尝试过这个,node.js。我得到一个...我不知道为什么尝试捕获无法得到它。Uncaught (in promise) Error: here

有人可以解开这个谜团吗?

fct = async (msg) => {
    throw new Error(msg)
}

delayedValue = (value) => new Promise((resolve) => setTimeout(() => resolve(value), 1000));

(async () => {
    try {
        console.log(await Promise.all([
            fct(await delayedValue('here')),
            fct(await delayedValue('it is')),
        ]));
    } catch (e) {
        console.error('catched', e);
    }
})();
JavaScript 异常 async-await try-catch

评论

1赞 freedomn-m 4/18/2023
这个答案可能会有所帮助。
0赞 Bergi 4/18/2023
你为什么要在参数中使用内部?awaitPromise.all
0赞 Poyoman 4/18/2023
@HeikoThei ßen 使用节点 v18.15.0 我得到这个输出: ''' > 未捕获的错误:在 fct (REPL3:2:11) >捕获 错误:在 fct (REPL3:2:11) (node:70851) PromiseRejectionHandledWarning:异步处理 Promise 拒绝(拒绝 ID:1)(用于显示警告的创建位置)'''node --trace-warnings ...
1赞 Bergi 4/18/2023
@freedomn-m 其实不,它没有
1赞 freedomn-m 4/18/2023
@Bergi感谢您的反馈 - 我对异步异常进行了快速搜索,这是一个详细的答案。

答:

0赞 InSync 4/18/2023 #1

在 中,使 IIFE 等待 1 秒,然后传递给 ,而 又抛出错误。fct(await delayedValue('here'))awaitdelayedValue('here')'here'fct()

在事件循环的这个时候,还没有返回任何东西,这意味着 IIFE 仍在等待它并且没有执行。await delayedValue('it is')catch

话虽如此,最终还是发现了错误,但晚了一秒钟。catch

3赞 Bergi 4/18/2023 #2

问题在于 s 和 un-ed 异步函数调用的组合。代码的执行方式awaitawait

const value1 = await delayedValue('here');
const promise1 = fct(value1);
const value2 = await delayedValue('it is');
const promise2 = fct(value2);
await Promise.all([promise1, promise2]);

这是一个众所周知的反模式,它恰恰导致了您遇到的问题。 是一个承诺,在它通过附加 1 的处理程序之前被拒绝。在编辑承诺时,它已经被拒绝了,这会导致未处理的拒绝错误。promise1Promise.alldelayedValue('it is')await

目前尚不清楚您希望代码如何运行,您可能正在寻找以下任何一个

  • const value1 = await delayedValue('here');
    const value2 = await fct(value1);
    const value3 = await delayedValue('it is');
    const value4 = await fct(value3);
    console.log([value2, value4]);
    
  • const [value1, value2] = await Promise.all([
      delayedValue('here'),
      delayedValue('it is'),
    ]);
    console.log(await Promise.all([
      fct(value1),
      fct(value2),
    ]));
    
  • console.log(await Promise.all([
      delayedValue('here').then(fct),
      delayedValue('it is').then(fct),
    ]));
    
  • const value1 = await delayedValue('here');
    const [value2, value4] = await Promise.all([
      fct(value1),
      delayedValue('it is').then(fct)
    ]);
    console.log([value2, value4]);
    

所有这些都将快速失败,并立即处理周围/块中任何被调用函数的任何错误。trycatch

1:更准确地说,在同一个微任务(循环?)中,可能在承诺被拒绝之后,必须“立即”附加处理程序 - 当 fct() 返回已经被拒绝的承诺时,这很好。无论哪种方式,在附加拒绝处理程序之前,await delayedValue() 都是不可接受的。

评论

0赞 Poyoman 4/18/2023
感谢您易于理解的解释和参考。我想我仍然需要深入研究一下,才能完全理解这里发生的事情^^