catch必须放在Promise链末尾才能捕获任意环节错误,因错误会冒泡传递;需避免then中吞掉错误,推荐用catch替代onRejected参数;Promise.all后接catch可统一处理任一子promise失败,而allSettled不可。

在 JavaScript 中,catch 方法可以统一捕获 Promise 链条中任意环节抛出的错误(包括 reject 和同步异常),关键在于把它放在链的**末尾**,且确保前面每个 then 都不意外吞掉错误。
把 catch 放在链最末端
Promise 链是“冒泡式”传递拒绝态的:只要中间没有 catch 或带错误处理的 then(onFulfilled, onRejected),错误会一直向后传递,直到遇到第一个 catch。
✅ 正确写法(错误能被捕获):
fetch('/api/data')
.then(res => {
if (!res.ok) throw new Error('HTTP error');
return res.json();
})
.then(data => processData(data))
.catch(err => {
console.error('链中任一环节出错:', err);
});避免在 then 中意外“吞掉”错误
如果某个 then 的成功回调里抛出错误,但后续没有 catch,这个错误会丢失(变成 unhandled rejection)。同样,若用了 then(onFulfilled, onRejected) 却在 onRejected 里没重新抛出或返回 rejected promise,错误也会终止传播。
- ❌ 错误示范(吞掉错误,后续 catch 接不到):
Promise.resolve()
.then(() => {
throw new Error('被吞掉的错误');
}, () => {
// 这里只处理前一个 reject,不处理上面 throw 的错误
})
.catch(err => console.log('这不会执行')); // 不会执行- ✅ 推荐写法:用
catch替代第二个参数,保持错误流畅通:
Promise.resolve()
.then(() => {
throw new Error('明确抛出');
})
.catch(err => {
console.log('这里能捕获', err.message); // ✅ 能捕获
throw err; // 若需继续传递,可 re-throw
})
.catch(err => console.log('二次捕获'));多个并行 Promise 也适用 Promise.all + catch
Promise.all 在任意一个子 promise reject 时就立即 reject,因此可在其后直接接 catch 统一处理:
Promise.all([
fetch('/api/a'),
fetch('/api/b'),
fetch('/api/c')
])
.then(([a, b, c]) => /* 处理全部成功 */)
.catch(err => {
console.error('其中一个请求失败:', err);
});⚠️ 注意:Promise.allSettled 不会 reject,所以不能靠它后面的 catch 捕获失败 —— 它总是 fulfilled,需手动检查每个结果的 status 字段。
顶层兜底:全局 unhandledrejection 监听(辅助调试)
即使写了 catch,仍可能因疏漏导致错误未被捕获。可在全局监听作为最后防线(仅用于日志或监控,**不能替代链内 catch**):
window.addEventListener('unhandledrejection', event => {
console.warn('未捕获的 Promise 拒绝:', event.reason);
event.preventDefault(); // 阻止默认控制台警告(可选)
});该事件无法恢复 Promise 链,仅作提醒和上报用途。


















