try-catch仅捕获同步错误,异步错误需用async/await配合或.catch()处理;Promise构造函数内同步错误转reject但不触发外层catch;unhandledrejection仅用于日志上报,不可替代主动错误处理。
很多人把 fetch 或 setTimeout 套进 try 块里,结果错误照样冒泡到全局。这是因为 try-catch 作用域只覆盖当前执行栈,而异步回调在后续事件循环中运行,已脱离原 try 上下文。
JSON.parse('invalid')、undefined.foo)能被正确捕获Promise 构造函数内部抛出的同步错误(如 new Promise(() => { throw new Error('boom') }))会被自动转为 reject,但不会触发外层 catch
try-catch 管到异步逻辑,得配合 async/await —— 它让 Promise 链“看起来像同步”,从而让 catch 生效只要函数声明为 async,内部 await 的 Promise 被 reject,就会像抛异常一样被 catch 捕获。不需要手动写 .catch(),代码更线性,错误堆栈也更清晰。
async function loadData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
return data;
} catch (err) {
console.error('加载失败:', err.message);
// 这里能拿到 fetch 失败、JSON 解析失败、甚至 res.ok 判断抛出的错误
}
}
await 后面必须是 Promise,否则不会等待,也不会触发 catch
await 可共用一个 try-catch,但要小心前序失败导致后续不执行await 连写,改用 Promise.allSettled 或单独 .catch()
当不使用 async/await,或需要对单个 Promise 做独立错误处理时,.catch() 更灵活。它只捕获前一个 Promise 的 reject,不影响后续链上其他 Promise 的状态。
fetch('/api/users')
.then(res => {
if (!res.ok) throw new Error('Users API failed');
return res.json();
})
.then(users => {
return fetch(`/api/profile/${users[0].id}`);
})
.then(res => res.json())
.catch(err => {
console.error('任一环节出错:', err.message);
});
.catch() 是链式终点,一旦触发,后续 .then() 不再执行(除非你在 catch 里返回新值或 Promise)catch 里返回一个默认值或 Promise.resolve(...)
.catch(() => {}) 却不处理或 re-throw,这会让错误静默消失,调试困难浏览器和 Node.js 都提供 window.addEventListener('unhandledrejection'),但它只是最后警报,不是错误处理机制。等走到这一步,说明你漏掉了所有 catch 或 try-catch。
,比如发送错误信息到监控服务:event.reason 就是被 reject 的值unhandledrejection 里尝试“修复”逻辑 —— 此时上下文早已丢失,补救无效.catch(),或每个 await 都在 try 内async 函数里调用了没 await 的 Promise,或者 Promise.all([p1, p2]) 中某个失败却没处理 rejection。这类问题不会立即报错,但会在特定数据路径下突然崩溃。