async函数中异常会自然向上冒泡,需在调用链上层用try/catch或Promise链末尾加.catch()捕获;await使rejection转为同步异常;应集中处理而非每层重复;须保留原始堆栈,避免手动new Error;构造器内异步错误需单独处理。

async 函数中深层调用的异常会自然向上冒泡,但必须被正确捕获,否则会变成未处理的 Promise rejection。关键不是阻止冒泡,而是确保它在合适的位置被捕获——要么在调用链上层用 try/catch 拦截,要么在 Promise 链末尾加 .catch()。
async/await 中的 try/catch 是主要防线
await 会把 Promise 的 rejection 转为同步可捕获的异常,所以最直接的方式就是在 async 函数内部或调用处包裹 try/catch:
- 错误发生在 await 后的任意层级(比如 fetch → service → utils),只要没被中途 catch,就会一直冒泡到最近的 try/catch 块
- 不建议在每一层都加 try/catch;应集中在业务入口、API 调用点或用户操作触发处统一处理
- 示例:await 一个深层函数时,错误仍会抛到外层 try 中,无需在中间层重复处理
Promise 链里的 .catch() 不能漏掉
如果使用 .then().catch() 风格,错误冒泡只认链上后续的 .catch(),不会“回溯”找前面的:
- 每个 .then() 返回新 Promise,错误只在这个新链里冒泡;若链尾没 .catch(),就成未捕获错误
- 避免写成:
.then(() => doAsync()).then(...)却忘了最后加 .catch() - 推荐写法:Promise 链始终以 .catch() 收尾,或统一转为 async/await + try/catch
跨层级传递错误时保留原始堆栈
深层抛出的错误默认保留完整调用栈,但要注意两种破坏堆栈的情况:
- 手动 new Error() 并 throw,会丢失原始堆栈;应直接 throw 原始 error 对象
- 在 Promise 构造器里 reject(new Error()),也切断了链路;优先用 async/await 或 Promise.reject(err) 保持上下文
- 必要时可用
err.cause = originalErr或throw err from originalErr(Python)显式关联
异步构造器或初始化阶段的错误要特别对待
像 class 构造函数中调用 super() 触发的同步错误会立即冒泡,但构造器里启动的异步操作(如 fetch)失败不会自动冒泡:
- new 实例时发生的同步错误(如参数校验失败)可被外层 try/catch 捕获
- 但 constructor 内部的 await 操作出错,属于 Promise rejection,需单独监听或返回 Promise 让调用方处理
- 稳妥做法:构造器不执行异步逻辑;把初始化逻辑拆到独立的 init() 方法,并明确返回 Promise

















