process.on('uncaughtException') 不捕获 Promise 拒绝错误,仅处理同步异常和非 Promise 回调中的 throw;Promise 错误必须由 process.on('unhandledRejection') 兜底,否则静默丢失、导致业务异常不被发现。

Node.js 中 process.on('uncaughtException') 不捕获 Promise 拒绝类异步错误,它只处理同步异常或回调中抛出的、未被任何 try-catch 捕获的错误。而 Promise 内部(包括 .then、.catch、async/await 函数体)抛出的错误,走的是独立的 rejection 路径,必须由 process.on('unhandledRejection') 来兜底。
uncaughtException 的真实作用范围
它监听的是「未被捕获的同步异常」以及「在回调函数中直接 throw 的错误」,前提是这些回调本身不是 Promise 链的一部分。例如:
- fs.readFile 的 callback 里
throw new Error()→ 会被uncaughtException捕获 - setTimeout 回调里
throw new Error()→ 会被捕获 - 但
Promise.resolve().then(() => { throw new Error() })→ 不会触发uncaughtException,只会变成未处理的 rejection
为什么 unhandledRejection 是必须的
Promise 的错误路径与传统调用栈无关。一旦 Promise 被 reject 且没有 .catch 或 await 的 try-catch 接住,错误就脱离了 JavaScript 异常传播机制,转为事件循环层面的「未处理拒绝」。这种错误:
- 不会中断进程(默认行为),但可能让应用进入不一致状态
- 控制台仅显示
Uncaught (in promise),不触发任何已有监控 - 像支付失败、数据解析中断这类问题,可能静默发生数天而不被发现
两者配合使用的典型模式
一个健壮的 Node.js 应用应同时注册两个监听器,并做差异化响应:
立即学习“Java免费学习笔记(深入)”;
-
uncaughtException:记录日志 + 尝试优雅关闭(如停止接受新请求),然后退出进程。因为此时调用栈已损坏,继续运行风险高 -
unhandledRejection:记录拒绝原因 + 主动调用process.exit(1),避免进程带病运行。注意不要仅打印日志就放任不管
常见误用与规避建议
很多人以为加了 uncaughtException 就万事大吉,结果线上大量 Promise 错误被吞掉。要避免这类陷阱:
- 所有
async函数入口都应包裹 try-catch,尤其 HTTP 处理器、定时任务、消息消费逻辑 - 每个 Promise 链末尾显式加
.catch(console.error),或统一用process.on('unhandledRejection')补漏 - 开发阶段启用
--unhandled-rejections=strict,让未处理 rejection 直接崩溃,强制暴露问题


















