async函数中try-catch仅能直接捕获同步错误和await触发的Promise拒绝,无法捕获未await的Promise错误或setTimeout等顶层异步异常;需通过await显式等待、Promise.all统一处理、unhandledrejection全局监听及回调内手动try-catch来覆盖各类错误场景。

在 async 函数中,try catch 只能直接捕获同步错误和被 await 触发的 Promise 拒绝(即 rejected promise),无法自动捕获未 await 的 Promise 错误或顶层异步错误(如 setTimeout 中抛出的异常)。要可靠捕获多类错误,关键在于明确错误来源并统一处理策略。
捕获 await 表达式中的 Promise 拒绝
这是最常见也最推荐的用法。只要 Promise 被 await,其 rejection 就会以异常形式进入 catch 块。
- 确保所有异步操作都显式 await,否则错误不会进入 try catch
- 避免在 try 块中漏掉 await,例如 fetch(url).then(...) 不会触发 catch,而 await fetch(url) 会
- 注意:fetch 成功返回 Response 对象,但 404/500 等 HTTP 错误不会自动 reject,需手动检查 response.ok 或调用 response.json() 等方法才可能 throw
统一处理多个异步调用的错误
当需要并发执行多个异步操作并集中捕获任一失败时,不建议对每个 await 单独 try catch,而是用 Promise.all 或 Promise.allSettled 配合外层 try catch。
- 使用 Promise.all([...]):任一 Promise reject,整个 all 立即 reject,catch 可捕获该错误
- 使用 Promise.allSettled([...]):始终 resolve,返回每个 Promise 的状态对象,适合需区分成功/失败的场景
- 避免写成 await promise1(); await promise2(); —— 第二个失败时第一个已执行完,无法“同时”捕获
捕获未 await 的 Promise 错误(如事件回调、定时器)
这类错误脱离 try catch 作用域,需单独监听:
- 全局 unhandledrejection 事件可捕获未处理的 Promise rejection:window.addEventListener('unhandledrejection', e => {...})
- Node.js 中监听 process.on('unhandledRejection', ...)
- 对 setTimeout/setInterval 中可能 throw 的代码,应在回调内自行 try catch,不能依赖外层 async 函数
区分错误类型并做针对性处理
catch 到的 error 是普通 Error 实例或自定义错误,可通过 instanceof、error.name 或 error.code 判断类型:
- 网络错误常用 error.name === 'TypeError'(如 fetch 跨域失败)或 error.message.includes('fetch')
- API 业务错误常由后端返回,需解析响应体后 throw 自定义错误(如 ApiError),再用 error instanceof ApiError 区分
- 避免仅靠 typeof error === 'string' 判断,应优先使用标准 error 属性

















