如何正确使用 uncaughtException ?
发布于 2 年前 作者 NiLinli 2747 次浏览 来自 问答

最近在看狼书里面提到捕获 uncaughtException 异常防止 process 退出。 看了一下 Node 文档, 提到

需要注意,如果打算使用 ‘uncaughtException’ 事件作为异常处理的最后补救机制,这是非常粗糙的设计方式

感觉对 uncaughtException 使用场景很迷茫,麻烦指点一下。

3 回复

The correct use of ‘uncaughtException’ is to perform synchronous cleanup of allocated resources (e.g. file descriptors, handles, etc) before shutting down the process. It is not safe to resume normal operation after ‘uncaughtException’.

To restart a crashed application in a more reliable way, whether ‘uncaughtException’ is emitted or not, an external monitor should be employed in a separate process to detect application failures and recover or restart as needed.

文档里面也描述了,使用 uncaughtException 的正确方式就是在它的回调里面做一些同步的资源释放和错误记录工作,但是不能在里面进行程序的错误恢复,因为此时的程序运行状态是不可预测的,如果有恢复程序的需求,应该在守护进程中完成,类似常用的 pm2

确实是为了防止进程退出的,我一般uncaughtException和unhandledRejection都只是收集错误,因为这相当于是保证程序继续运行最后的手段,所以必需让这两个事件极少发生,甚至是绝不发生 uncaughtException最常见的就是 TypeError: Cannot read property ‘prop’ of null ,就是访问对象的属性前没检查对象是否为null或undefined unhandledRejection就是promise对象没有catch

process.on('uncaughtException', (err) => {
    console.error('my uncaughtException:', err);
});

process.on('unhandledRejection', (err) => {
    console.error('my unhandledRejection:', err);
});

setInterval(() => {
    console.log(obj.abc)  // 访问对象前未检查,导致uncaughtException,如果没有监听这个事件,程序必定挂掉
    Promise.reject(11)  // 没有对promise对象进行catch,导致unhandledRejection,但如果没有监听这个事件,程序也还能继续运行
}, 1000);

setInterval(() => {
    console.log(new Date())
}, 3000);

并不是说这两个事件发生了就一定要关闭资源退出,曾经公司的另一个项目(其它同事负责)出现过一次生产事故,因为某开源模块也监听了这两个事件并且居然强行process.exit(),导致服务进程无限重启,实际上并没有什么影响(欢迎大佬提供典型案例指正)

Attempting to resume normally after an uncaught exception can be similar to pulling out of the power cord when upgrading a computer — nine out of ten times nothing happens - but the 10th time, the system becomes corrupted.

回到顶部