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

wil*_*msi 6 javascript asynchronous

async asyncfunction(){
  try{
    await method1();
    await method2();
  }
  catch(error){
    console.log(error);
  }
}
Run Code Online (Sandbox Code Playgroud)

给定method1()和method2()是异步函数.每个await方法都应该有一个try/catch块吗?是否有更清晰的方式来写这个?我试图避免'.then'和'.catch'链接.

Eya*_*oth 13

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

下面的代码片段是不安全的:

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

    await p1;
    await p2;
  } catch (e) {
    console.log(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

如果两个承诺都被拒绝,则代码将导致UnhandledPromiseRejectionWarningNodeJS,如果该选项--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);
}
Run Code Online (Sandbox Code Playgroud)

只有第一个被拒绝的承诺才会“触发”该catch子句,而第二个承诺将被默默地忽略而不会导致进程崩溃。


tra*_*r53 12

使用包含多个await操作的一个try/catch块很好.

await运营商存储其父async功能执行上下文,并返回到事件循环.await当使用已结算的状态和操作数的值回调操作符时,将重新执行操作符.

在恢复时,await恢复先前保存的执行上下文并返回操作数promise的履行值作为await表达式的结果,或者抛出拒绝操作数的拒绝原因.

所述try/catch块调用是之前和被保存和恢复后的执行上下文的一部分.因此,多个await操作不会干扰try它们共享的外部块的行为.该catch块将与期待已久的任何承诺的拒绝理由被调用try被拒绝块.