promise链中未处理的异常不会被try...catch捕获,也不会触发uncaughtexception,必须通过process.on('unhandledrejection')(node.js)或window.addeventlistener('unhandledrejection')(浏览器)监听兜底,仅用于日志、监控或告警,不可恢复逻辑。

Promise 链中未处理的异常(unhandled rejection)不会被 try...catch 捕获,也不会触发全局 catch,容易静默失败。关键是要主动监听并响应未处理的 Promise 拒绝。
使用 unhandledrejection 全局事件监听
浏览器和 Node.js(v15+)都支持 unhandledrejection 事件,它是捕获“漏网之鱼”的最后一道防线:
- 在浏览器中监听
window;在 Node.js 中监听process - 事件对象包含
reason(拒绝值)和promise(出问题的 Promise 实例) - 仅用于日志、监控或兜底告警,**不能用来恢复逻辑**(此时 Promise 已不可挽回)
window.addEventListener('unhandledrejection', event => {
console.error('Unhandled rejection:', event.reason);
// 上报错误、触发告警等
event.preventDefault(); // 阻止默认控制台警告(可选)
});
在 Promise 链末尾加 .catch()
最直接有效的方式:确保每个 Promise 链都有终结性的错误处理。
- 避免链式调用以
.then()结尾(如fetch(...).then(...)),这会让拒绝“掉出链外” - 即使你只关心成功,也应显式加
.catch(() => {})或至少记录错误 - 推荐写法:
promise.then(handleSuccess).catch(handleError)
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data)); // ❌ 没有 catch,网络错误或 JSON 解析失败将无人处理
用 async/await 配合 try/catch 更可控
相比纯 Promise 链,async/await 让错误流更接近同步代码,降低遗漏概率:
- 所有 Promise 拒绝都会被同层
try/catch捕获(包括await后的任意 Promise) - 注意:多个并行
await不会自动聚合错误,需手动包裹或使用Promise.allSettled - 仍建议对顶层 async 函数补充
unhandledrejection监听,作为兜底
async function loadData() {
try {
const res = await fetch('/api/data');
const data = await res.json();
console.log(data);
} catch (err) {
console.error('加载失败:', err);
}
}
工具辅助:ESLint 规则 + 测试覆盖
靠人眼检查易疏漏,可用工程化手段预防:
- 启用 ESLint 插件(如
eslint-plugin-promise)的always-catch或avoid-new-line-in-promise-chain规则 - 单元测试中模拟 Promise 拒绝,验证错误路径是否被正确处理
- CI 环节可配置检测未处理 rejection 的运行时断言(例如在 Puppeteer 或 Jest 中监听
unhandledrejection并 fail 测试)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











