Promise.all 中无法捕获的异常

问题描述 投票:0回答:2

我在浏览器和 node.js 中试过了。我得到一个

Uncaught (in promise) Error: here
...我不知道为什么try catch不能得到它。

有人能解开这个谜吗?

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 exception async-await try-catch
2个回答
1
投票

问题是

await
s 和 un-
await
ed 异步函数调用的组合。代码执行为

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

这是一个 众所周知的 反模式,它会导致您遇到的问题。

promise1
是一个在通过 Promise.all 附加处理程序
1
之前被拒绝的承诺。当
delayedValue('it is')
承诺被
await
ed 时,它已经被拒绝了,这会导致未处理的拒绝错误。

不清楚您希望代码如何运行,您可能正在寻找任何

  • 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]);
    

所有这些都将快速失败,并立即在周围的

try
/
catch
块中处理来自任何被调用函数的任何错误。

1:更准确地说,处理程序必须在同一个微任务(循环?)期间“立即”附加,可能是在承诺被拒绝之后——当

fct()
返回一个已经被拒绝的承诺时就可以了。无论哪种方式,
await delayedValue()
在附加拒绝处理程序之前都是不可接受的。


0
投票

fct(await delayedValue('here'))
中,
await
使IIFE等待
delayedValue('here')
1秒,然后将
'here'
传递给
fct()
,这又会引发错误。

在事件循环的这个时候,

await delayedValue('it is')
还没有返回任何东西,这意味着IIFE还在等待它,还没有执行
catch
.

话虽这么说,

catch
最终发现了错误,但晚了一秒钟。

© www.soinside.com 2019 - 2024. All rights reserved.