我可以在异步函数的 try/catch 块中使用多个“await”吗?

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

async asyncfunction(){
  try{
    await method1();
    await method2();
  }
  catch(error){
    console.log(error);
  }
}

给定 method1() 和 method2() 是异步函数。每个await 方法都应该有一个try/catch 块吗?有没有更干净的方法来写这个?我试图避免“.then”和“.catch”链接。

javascript asynchronous
3个回答
47
投票

在等待

await
一元运算符右侧创建的 Promise 时,使用包含多个
await
操作的一个 try/catch 块是可以的:

await
运算符存储其父
async
函数的执行上下文并返回到事件循环。当使用其操作数的已确定状态和值进行回调时,
await
运算符的执行将恢复。

恢复后,

await
恢复之前保存的执行上下文,并返回操作数承诺的已完成值作为
await
表达式的结果,或抛出拒绝操作数的拒绝原因。

try/catch
块调用是保存和恢复之前和之后执行上下文的一部分。因此,多个
await
操作不会干扰它们共享的外部
try
块的行为。
catch
块将被调用,并带有在被拒绝的
try
块中等待的任何承诺的拒绝原因。

未捕获拒绝警告

如果代码

await
的 Promise 不是由
await
运算符的参数表达式创建的,并且没有拒绝处理程序,则在执行
await
运算符应用于它们之前,这些 Promise 不会有拒绝处理程序运行时

如果在

await
将处理程序添加到此类 Promise 之前触发 try/catch 块,并且它们拒绝,则会发生未捕获的拒绝错误。感谢@EyolRoth 的警告,请参阅他的 answer 以获取案例示例。

建议:如果您需要等待之前创建的且没有错误处理程序的承诺,请仔细考虑。然后检查如何将其创建移动到

await
的操作数表达式。


13
投票

虽然@traktoranswer是正确的,但我想添加一个非常重要的警告。

以下代码片段不安全:

async function foo() {
  try {
    const p1 = method1();
    const p2 = method2();

    await p1;
    await p2;
  } catch (e) {
    console.log(e);
  }
}

如果两个 Promise 都被拒绝,则代码将导致 NodeJS 中出现

UnhandledPromiseRejectionWarning
,如果选项
--unhandled-rejections
设置为
throw
(这将成为 Node 15 的默认行为),则可能会终止进程。

为什么会出现这种情况?

在问题的原始代码中,异步方法是顺序调用的;即,如果第一个方法失败(承诺被拒绝),则永远不会调用第二个方法。

但是,本答案开头的代码并行调用这两个异步方法;即,无论第一个方法是否成功,都会调用第二个方法。

在这种情况下,只有第二个方法的承诺中的

await
以第一个方法的成功为条件。这意味着,如果第一个方法失败,则永远不会等待第二个方法(已经开始)的 Promise,因此如果它也失败,则会导致已处理的 Promise 拒绝。

如何克服这种行为?

假设我们希望以相同的方式处理两个拒绝,我们可以使用 Promise.all:

try {
  const p1 = method1();
  const p2 = method2();
  
  await Promise.all([p1, p2]);
} catch (e) {
  console.log(e);
}

只有第一个被拒绝的承诺才会“触发”

catch
子句,而第二个承诺将被默默地忽略而不会导致进程崩溃。


0
投票

使用 Async.js 库 让我们谈谈如何使用 async.js 库以避免回调地狱。

根据 async.js 的官方网站:Async 是一个实用程序模块,它为使用异步 JavaScript 提供了直接、强大的功能。

Async.js 总共提供了近 70 个左右的函数。现在,我们只讨论其中两个,即 async.waterfall() 和 async.series()。

async.waterfall() 当您想要一个接一个地运行一些任务,然后将前一个任务的结果传递到下一个任务时,此方法非常有用。它需要一个函数“任务”数组和一个最终“回调”函数,该函数在“任务”数组中的所有函数完成后调用,或者使用错误对象调用“回调”。

async.js 库

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