Promise错误未捕获会在本轮事件循环结束、微任务队列清空后触发unhandledrejection事件,若无监听器则抛出UnhandledRejection错误;需在Promise链末尾加.catch或用try/catch包裹await,并避免catch中再抛未处理错误。

Promise的错误如果不捕获,会在事件循环的末尾触发 unhandledrejection 事件,如果该事件没有监听器,浏览器或Node.js就会抛出 UnhandledRejection 错误(通常显示为警告或崩溃)。
Promise拒绝后未处理的时机
当一个 Promise 被 reject,且在它被 settle(即进入 fulfilled 或 rejected 状态)后的**本轮事件循环结束时**,JavaScript 引擎会检查它是否已被 catch 或通过 .then(null, handler) 处理。如果没有,就视为“未处理的拒绝”。
- 这个检查发生在微任务队列清空之后、下一个宏任务开始之前
- 即使后面写了
catch,只要不在当前微任务阶段链上,也算未及时处理 - 例如:把
catch放在定时器、点击事件里,不算有效处理
常见导致 UnhandledRejection 的写法
以下代码都会触发 unhandledrejection(除非全局加了监听):
-
Promise.reject(new Error('oops'))—— 没有任何链式调用 -
fetch('/api').then(res => res.json())—— 只处理成功,没接catch,JSON 解析失败就漏掉 -
async function foo() { throw new Error('boom'); } foo();—— async 函数返回的 Promise 被拒绝,但没被 await 或 catch
如何避免和排查
关键是让每个 Promise 链都有明确的错误出口:
立即学习“Java免费学习笔记(深入)”;
- 始终在 Promise 链末尾加上
.catch(e => {/* 处理或上报 */}) - 使用
async/await时,用try/catch包裹可能出错的 await 表达式 - 开发期可加全局监听快速发现:
<script>window.addEventListener('unhandledrejection', e => console.error('未捕获拒绝:', e.reason));</script> - Node.js 中可通过
process.on('unhandledRejection', ...)捕获并退出进程(避免静默失败)
注意:已处理但又抛出新错误仍可能触发
比如 .catch(() => { throw new Error('new error'); }),这个新错误会生成一个新的未处理 Promise 拒绝——所以 catch 里也要小心别再抛错,或确保它也被后续处理。


















