try/catch 仅配合 async/await 才能捕获 await 异常,promise 链必须靠末尾 .catch() 兜底;fetch 需手动检查 res.ok,多个 await 可共用 try/catch,避免在 foreach 中 await,应改用 for…of 或 promise.all;未捕获的 promise 拒绝需用 unhandledrejection 监听但不可替代主动处理。

try/catch 本身不处理异步错误,只有配合 async/await 才能真正捕获 await 表达式抛出的异常;Promise 链则必须靠 .catch() 放在末尾来兜底——这是两种互补、不可互相替代的机制。
async/await 中必须用 try/catch 包裹 await
async 函数让异步代码“看起来同步”,但前提是错误要落在 try 块内。单独写 await 不加 try/catch,一旦 Promise 被 reject,就会变成未捕获异常。
- fetch 默认不因 HTTP 状态码(如 404、500)reject,需手动检查 res.ok 并 throw 错误
- 多个 await 可共用一个 try/catch,适合有依赖关系的串行操作
- 不要在 forEach 或 map 中直接 await 异步回调,应改用 for…of 或 Promise.all + map
Promise 链必须在末尾接 .catch()
.then() 的回调里哪怕只有一行代码出错(比如 JSON.parse 失败、undefined 调用方法),也会被链尾的 .catch() 捕获。漏掉 .catch() 就等于放任错误静默逃逸。
- 错误会沿链向后冒泡,中途没有 .catch() 就一路传到最末端
- .catch() 既能捕获网络失败,也能捕获 .then() 内部同步错误,一并接管
- 若需区分不同阶段错误,可在中间 .then() 后加局部 .catch(),再用 resolve 继续链路
避免常见陷阱:构造函数、定时器与裸 Promise
new Promise(() => { throw new Error() }) 这类同步抛错会被自动转为 reject,但外层 try/catch 依然抓不到;setTimeout 里的 throw 更是彻底脱离执行栈。
- Promise 构造器中出错 → 必须用 .catch() 或 await 才能捕获
- 定时器、事件监听器等原生异步场景 → 无法用 try/catch,只能靠 reject + .catch() 或 async/await 封装
- 不要写 Promise.reject().catch() 以外的“裸 reject”,否则容易触发 unhandledrejection
补充策略:allSettled 与全局兜底
当多个异步任务需要并行执行且彼此独立时,Promise.all 一错全停,而 Promise.allSettled 返回每个任务的完整状态,便于分别处理成功与失败。
- window.addEventListener('unhandledrejection', e => console.warn('未处理的 Promise 拒绝:', e.reason)) 只用于日志,不能替代主动捕获
- 业务关键路径上,建议在顶层 async 函数或请求入口统一加 try/catch,配合错误分类和降级逻辑
- 对 fetch、localStorage 等可能失败的操作,提前封装成带默认返回或重试机制的工具函数











