
`unhandledrejection` 是浏览器中全局分发的 dom 事件,用于捕获未被 catch 的 promise 拒绝;它**不会中断脚本执行**,仅作为调试与监控机制存在,不影响页面交互或后续代码运行。
unhandledrejection 事件常被误解为“作用域级错误”或“脚本终止信号”,但事实并非如此。这里的“global scope of a script”并非指 JavaScript 的词法作用域(如函数或块级作用域),而是指事件分发的目标对象——即全局执行环境的代表对象:在浏览器主线程中是 window,在 Web Worker 中是 self。该事件本质上是一个标准 DOM 事件,遵循事件冒泡规则(尽管它不冒泡到父元素,只在全局对象上触发),因此可通过 window.addEventListener('unhandledrejection', ...) 或简写 addEventListener('unhandledrejection', ...) 进行监听。
关键点在于:它不阻塞执行流,也不导致脚本崩溃。例如以下代码会正常输出三行日志,并继续执行后续语句:
addEventListener('unhandledrejection', (event) => {
console.log('unhandledrejection');
console.log('Promise:', event.promise);
console.log('Reason:', event.reason);
// ⚠️ 注意:调用 event.preventDefault() 可阻止默认行为(如控制台警告),
// 但不会改变 Promise 已被拒绝的事实,也不会恢复执行。
});
Promise.reject('sss');
console.log('✅ 这行仍会执行'); // ✅ 正常输出输出结果为:
unhandledrejection
Promise: Promise {: "sss"}
Reason: sss
✅ 这行仍会执行 这清晰表明:Promise 拒绝本身是异步操作,unhandledrejection 仅是事后通知机制;JavaScript 引擎继续调度任务、响应用户交互、执行定时器等——整个应用保持完全可用。
⚠️ 注意事项:
- 该事件不可用于“挽救”已拒绝的 Promise(如自动 .catch())。它纯属观测用途,适合日志上报、错误监控或开发提醒;
- 若需防止 unhandledrejection 触发,应在 Promise 链末尾显式添加 .catch() 或 await 后包裹 try/catch;
- 在 Node.js 环境中行为不同:v15+ 默认将未处理拒绝视为致命错误并退出进程(可通过 process.on('unhandledRejection', ...) 捕获并 process.exitCode = 0 避免退出);
- 浏览器中即使不监听该事件,脚本也绝不会因此停止运行——最多仅在开发者工具控制台显示黄色警告。
总结:unhandledrejection 是一个诊断性、非侵入式的全局事件,设计初衷是帮助开发者发现遗漏的错误处理逻辑,而非控制程序生命周期。合理使用它可提升健壮性,但切勿将其误认为执行屏障或异常拦截层。










