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

新手上路,请多包涵

IE

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

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

原文由 williamsi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 915
2 个回答

使用一个包含多个 await 操作的 try/catch 块在等待 await 一元运算符右侧创建的承诺时很好:

await 运算符存储其父级 async 函数的执行上下文并返回到事件循环。 await 运算符的执行在其操作数的稳定状态和值被回调时恢复。

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

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

但是,如果代码 await 在同一个 try/catch 块中存在多个现有承诺,并且不止一个承诺被拒绝,则除了第一个拒绝之外的所有承诺都会生成未捕获的承诺拒绝错误。感谢@EyolRoth 提供此警告,请结合此问题阅读他的完整 答案

原文由 traktor 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

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

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

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

如果两个承诺都被拒绝,代码将在 NodeJS 中导致 UnhandledPromiseRejectionWarning ,如果选项 --unhandled-rejections 设置为 throw (这将成为节点 15 的默认行为)。

为什么会这样?

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

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

在这种情况下,只有 await 对第二种方法的承诺是以第一种方法的成功为条件的。意思是,如果第一个方法失败,则永远不会等待第二个方法(已经启动)的承诺,因此如果它也失败,将导致处理的承诺拒绝。

如何克服这种行为?

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

 try {
  const p1 = method1();
  const p2 = method2();

  await Promise.all([p1, p2]);
} catch (e) {
  console.log(e);
}

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

原文由 Eyal Roth 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题