JavaScript 中 async 函数定义中的异常处理覆盖范围

作者:袖梨 2026-07-02
async函数内try/catch仅捕获await等待的Promise拒绝、await后同步错误及thenable的then抛出异常;漏await、回调异步错误、未await的Promise等均不被捕获,需分层兜底处理。

async 函数内部的异常处理,只覆盖 该函数作用域内、且被 await 显式等待的 Promise 拒绝(reject)或同步抛出的错误。它不自动捕获未 await 的 Promise 错误、纯回调异步操作(如 setTimeout 回调、事件监听器)、或函数外部发生的异常。

哪些错误能被 try/catch 捕获

在 async 函数中,只有满足以下任一条件的错误才会进入其内部的 catch 块:

  • await 后面的 Promise 被 reject(例如 fetch 失败、API 返回 5xx、手动 throw new Error())
  • await 表达式之后、catch 之前出现的同步错误(如 JSON.parse 无效字符串、访问 undefined 属性)
  • await 等待一个 thenable 对象,其 then 方法执行时抛出异常

哪些错误不会被自动捕获

这些常见情况 不会触发 async 函数内的 try/catch

  • 漏写 await:直接调用 Promise 而不 await,错误会以 rejected Promise 形式返回,但不会中断函数执行,也不会进 catch
  • 未 await 的 Promise 链中的 reject(如 someApi().catch(handleErr) 写在 try 外)
  • setTimeout、setInterval 回调里的 throw
  • addEventListener 中的同步错误
  • Promise 构造函数里未被 await 的 reject(如 new Promise((_, reject) => reject('oops')) 但没 await 它)

异常传播路径很关键

async 函数本身总是返回 Promise。如果内部未捕获错误,这个 Promise 就会变成 rejected 状态。这意味着:

立即学习“Java免费学习笔记(深入)”;

  • 调用方可以用 .catch() 或外层 await + try/catch 接住它
  • 若调用方也未处理,错误最终会上抛到全局(可能触发 unhandledrejection 事件)
  • 错误不会“消失”,但若层层都不处理,就容易静默失败

推荐做法:按需分层兜底

不要把所有 await 塞进一个大 try 块。更合理的方式是:

  • 对强依赖的串行步骤(如用户 → 订单 → 详情),共用一个 try/catch,体现业务逻辑耦合性
  • 对可独立失败的操作(如并行加载头像和通知设置),分别 await 并各自 .catch() 或用 Promise.allSettled()
  • 在最外层调用处(如组件生命周期、事件处理器)加兜底 try/catch,防止未预期错误崩掉页面
  • 对特定错误类型(401、网络断连、解析失败)做差异化处理,而不是统一 console.error

相关文章

精彩推荐