未捕获的 promise 异常需通过全局监听 unhandledrejection 事件兜底:浏览器用 window.addeventlistener('unhandledrejection'),node.js 用 process.on('unhandledrejection'),仅捕获未被 .catch() 或 await 处理的拒绝,适用于日志、上报和告警,但不能替代源头主动处理(如 try/catch 包裹 await 或为每个 promise 显式添加 .catch())。

未捕获的 Promise 异常(Uncaught Promise Rejection)不会触发全局 try/catch,也不会中断主线程,但会在控制台报错,并可能影响应用稳定性。关键是要主动监听、拦截并妥善处理它们,而不是放任不管。
监听全局未捕获的 Promise 拒绝
使用 window.addEventListener('unhandledrejection')(浏览器)或 process.on('unhandledRejection')(Node.js)捕获所有未被 .catch() 或 await 处理的 Promise 拒绝。
- 浏览器中可记录错误、上报监控系统,或降级提示用户
- Node.js 中建议记录日志后退出进程(避免状态不一致),或根据业务决定是否继续运行
- 注意:该事件只触发一次,且仅对真正“未处理”的 Promise 生效(例如没写
.catch(),也没用await包裹)
避免依赖全局监听,优先在源头处理
全局监听是兜底手段,不能替代代码中显式的错误处理。每个 Promise 链都应有明确的错误出口:
- 使用
.catch()终止链路并处理异常,尤其在 API 调用、异步初始化等关键路径上 - 使用
async/await时,用try/catch包裹,确保异常不逃逸 - 避免“忘记
await”导致 Promise 泄漏——比如在循环或条件分支中创建 Promise 却没等待或捕获
识别和修复常见泄漏场景
有些写法看似正常,实则容易造成未捕获拒绝:
-
fetch('/api').then(data => ...)—— 缺少.catch(),网络失败或 JSON 解析错误会变成 unhandled rejection -
setTimeout(() => Promise.reject(new Error('oops')), 100)—— 定时器内创建的 Promise 无人监听 - 事件回调中返回 Promise 但未处理,如
button.addEventListener('click', () => api.submit().then(...)) - Vue/React 组件中发起请求却未在
mounted或useEffect里加.catch()或 try/catch
开发与测试阶段主动暴露问题
让未捕获拒绝更早暴露,减少上线后隐患:
- 开发环境开启严格模式:Chrome DevTools → Settings → “Break on caught exceptions” 可勾选 “Uncaught promise rejections”
- 在测试中模拟失败响应,验证错误路径是否被覆盖
- 使用 ESLint 插件(如
eslint-plugin-promise)检查缺失的.catch()或悬空 Promise - CI 流程中捕获 console.error 日志,对出现 unhandledrejection 的测试用例直接失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











