Node.js 在try/catch块中等待两个承诺将导致;未经处理的拒绝承诺”;
我想等待两个并行的承诺。我不想一次又一次地等待每一个承诺(虽然有效,但速度较慢) 出于这个原因,我认为我可以创建两个承诺,首先让它们运行,比如说两个网络请求,然后等待它们,并能够捕获catch块中的错误。这个假设似乎不正确,因为我在运行这个示例代码时收到了一个警告Node.js 在try/catch块中等待两个承诺将导致;未经处理的拒绝承诺”;,node.js,typescript,async-await,Node.js,Typescript,Async Await,我想等待两个并行的承诺。我不想一次又一次地等待每一个承诺(虽然有效,但速度较慢) 出于这个原因,我认为我可以创建两个承诺,首先让它们运行,比如说两个网络请求,然后等待它们,并能够捕获catch块中的错误。这个假设似乎不正确,因为我在运行这个示例代码时收到了一个警告 为什么呢 如何最好地使用优雅的代码并行运行两个或多个网络请求 为什么Typescript不警告我catch块将不可用 抓住拒绝 不会导致“捕获错误”输出,而是得到 tsc test-try-catch-await.ts &
- 为什么呢
- 如何最好地使用优雅的代码并行运行两个或多个网络请求
- 为什么Typescript不警告我catch块将不可用 抓住拒绝
tsc test-try-catch-await.ts && node test-try-catch-await.js
(node:31755) UnhandledPromiseRejectionWarning: b
(node:31755) 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:31755) [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.
Caught error b
(node:31755) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
让我们看看我能否以一种可以理解的方式来解释这一点,我们开始吧 创建
b promise
后,您的setTimeout
-调用的回调(即承诺的拒绝)被“推”到事件循环的计时器
队列中。现在,当事件循环进入下一次迭代时,承诺队列还没有处理await bPromise
,但是由于~100毫秒已经过去,回调被执行,您会得到未处理的承诺拒绝
错误
您需要立即等待新创建的承诺,因为事件循环的承诺微任务队列这次不会为空,现在将在处理计时器-队列中的回调之前执行,因此能够实际捕获错误:
const bPromise = await new Promise((_, reject) => {
setTimeout(() => reject('b'), 100);
});
我建议阅读并更好地掌握事件循环的工作原理。这是一种等待几个Promise
s来解析使用该函数的好方法。它需要一个Promise
s的Array
,并生成一个Promise
,该数组将解析为Array
,其中包含单个Promise
s解析为的值。此外,它仅在最后一个Promise
解析后解析。如果其任何输入Promise
s被拒绝,则整个Promise.all
表达式也会被拒绝。它有效地“同时”运行其所有输入进程,模仿经典的“fork-join”模式
出现该错误的原因是,一旦定义了这些承诺
s,超时过程就会启动,而不是在几行之后等待它们时启动。如果您在一个承诺
s的定义中记录一些文本,然后在等待
表达式之前记录其他内容,则可以看到这一点:
async function testMultipleAwait() {
try {
const aPromise = new Promise((resolve) => {
console.log('starting timeout');
setTimeout(() => resolve('a'), 200);
});
const bPromise = new Promise((_, reject) => {
setTimeout(() => reject('b'), 100);
});
console.log('awaiting');
const a = await aPromise;
const b = await bPromise;
} catch (e) {
console.log('Caught error', e);
}
}
testMultipleAwait();
// logs:
// "starting timeout"
// "awaiting"
要解决此即时问题,您可以将这些Promise
s转换为函数,然后调用它们,或wait
立即:
将这一切结合起来,让它们并行运行,您可以尝试以下方法:
async function testMultipleAwait() {
try {
await Promise.all([
new Promise(resolve => {
setTimeout(() => resolve("a"), 200);
}),
new Promise((_, reject) => {
setTimeout(() => reject("b"), 100);
})
]);
} catch (e) {
console.log("Caught error", e);
}
}
testMultipleAwait();
我想我知道问题是什么。即使承诺以并行方式启动,您仍在依次等待aPromise
和bPromise
:
const a = await aPromise; // First await this...
const b = await bPromise; // and then start to await this
当两个承诺都兑现时,这并不是什么大问题。这会让jou等待的时间和承诺的时间一样多。所有的人都会,然后愉快地继续。这就是为什么这个问题不是那么明显的原因
重要的是要知道,由于异步/等待,这个try-catch被转换为承诺。这意味着在等待的语句后面出现的任何内容都将以promise.then回调函数结束
因此,const b=await b promise
在const a
到达之前(200毫秒后)不会运行<代码>b Promise
提前100毫秒失败
这并不是说async/await不会发现错误,也不会将catch
块(作为promise.catch(…)一起附加到一起。毕竟,节点警告和捕获处理程序都有终端输出:
tsc test-try-catch-await.ts && node test-try-catch-await.js
1 first node sees the error > (node:31755) UnhandledPromiseRejectionWarning: b
2 (node:31755) 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)
3 (node:31755) [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.
4 and then your catch handler > Caught error b
5 (node:31755) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
因此,decatch子句确实有效,但异步函数在至少200毫秒之后才将其附加到bPromise
。第5行似乎证实了这一点:
PromiseRejectionHandledWarning: Promise rejection was handled asynchronously.
一旦为空,就会抛出拒绝错误
拒绝承诺已经处理,但node认为你太迟了。您可以使用修复此问题。这样,您将等待一次,异步函数将首先捕获每个潜在错误
// Everything just as it is.. and then:
const [a, b] = await Promise.all([
aPromise,
bPromise,
]);
因为好奇,我在chrome控制台中输入了你的代码,看看会发生什么。一个错误日志会弹出很短的时间(我猜是100毫秒)。看看这个输出,你可以听到chrome说:
“啊,等等!它终于被抓住了。这是消息!”
为什么会超过100毫秒?如果我将时间设置为8000和7000,则会出现相同的错误。请注意,切换计时顺序可以使代码正常工作。奇怪的是,也许我遗漏了什么,我会调查一下——同时,也许某位专业人士可以帮你解决。对不起:)
tsc test-try-catch-await.ts && node test-try-catch-await.js
1 first node sees the error > (node:31755) UnhandledPromiseRejectionWarning: b
2 (node:31755) 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)
3 (node:31755) [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.
4 and then your catch handler > Caught error b
5 (node:31755) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
PromiseRejectionHandledWarning: Promise rejection was handled asynchronously.
// Everything just as it is.. and then:
const [a, b] = await Promise.all([
aPromise,
bPromise,
]);