我正在读described on MDN的“等待循环”。它看起来令人印象深刻,所以我玩了一些代码,但令人惊讶的是我无法捕捉到那里抛出的错误。
'use strict';
const main = async() => {
const bar = [];
bar.push(new Promise((res) => { setTimeout(() => res(1), 1200); }));
bar.push(new Promise((res) => { setTimeout(() => res(2), 800); }));
bar.push(new Promise((res, rej) => { setTimeout(() => rej(3), 200); }));
try {
for await (const foo of bar) {
console.log('hey', foo);
}
} catch (err) {
console.error('err', err);
}
};
main();
主要是我的输出与我期望的一样。但是我不明白,为什么我得到了UnhandledPromiseRejection?我什至没有抓住那个错误?
$> node await-loop.js
(node:10704) UnhandledPromiseRejectionWarning: 3
(node:10704) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10704) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
hey 1
hey 2
err 3
(node:10704) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
有人可以帮我理解并在此处写下正确的流行语吗?我想念什么吗?
答案 0 :(得分:0)
未处理的承诺否决?
我什至没有抓住那个错误?
从理论上讲,是的。 (那么,那是catch块的正确选择?)
技术上没有。
Main Stack
| try |
| |
| await bar[0] | <-- waiting to resolve till sometime after 1200
| |
| catch |
| |
(大约)200毫秒后:
bar [2]被拒绝并被推送到队列,但是等待仍未屈服,因为它仍在等待bar [0]屈服,只有在1200毫秒后才会发生
因此,在拒绝bar [2]的时间中,没有catch
块可用来处理rejected promise
。请参见上面的堆栈,请注意,在拒绝时,try..catch
和bar[2]
不在同一堆栈中,至少与编译器(或概念上针对javascript)不一样。
但是您注意到:err 3
最终等待时捕获块捕获的bar[2]
如果更改承诺的顺序并将拒绝的承诺作为数组中的第一项,您会看到catch块很好地工作。
或者等待不同的时间:
// unhandled rejection
try {
await bar[0]
await bar[1]
await bar[2]
} catch (e) {
console.error('error', e)
}
// Catch successfull
try {
await bar[2]
await bar[0]
await bar[1]
} catch (e) {
console.error('error', e)
}
更新:
更好的方法是使用Promise.all
,它具有快速失败的行为。
try {
const datas = await Promise.all(bar)
} catch (e) {
console.error(e)
}
答案 1 :(得分:0)
for await of
循环只是同步for of
循环的简写语法,循环主体中有await
。因此,您可以通过以下方法实现所需的目标:
'use strict';
const main = async() => {
const bar = [];
bar.push(new Promise((res) => { setTimeout(() => res(1), 1200); }));
bar.push(new Promise((res) => { setTimeout(() => res(2), 800); }));
bar.push(new Promise((res, rej) => { setTimeout(() => rej(3), 200); }));
for (const foo of bar) {
try {
const result = await foo;
console.log('hey', result);
} catch (err) {
console.error('err', err);
}
}
};
main();
顺便说一句,如果您想知道引发错误的承诺,那么Promise.allSettled
可能更接近您想要的内容和更简洁的代码:
'use strict';
const main = async() => {
const bar = [];
bar.push(new Promise((res) => { setTimeout(() => res(1), 1200); }));
bar.push(new Promise((res) => { setTimeout(() => res(2), 800); }));
bar.push(new Promise((res, rej) => { setTimeout(() => rej(3), 200); }));
const results = await Promise.allSettled(bar);
/* Outputs:
[
{ status: 'fulfilled', value: 1 },
{ status: 'fulfilled', value: 2 },
{ status: 'rejected', reason: 3 }
]
*/
console.log(results);
};
main();