Node.js js 的执行是单线程的,在 Node14
及以前的版本,同步任务同抛错未处理程序则会终止,异步任务同抛错未处理则不会,而是出一个 warning
, 提示有 UnhandledPromiseRejectionWarning
的异常。
而在Node14
以后的版本,就算是异步任务同抛错未处理程序也会直接终止了。
Node14及以前的版本代码示例:
PS: 加一个sleep
函数的目的只是让程序别马上退出,验证是否是抛错导致的进程退出。
function sleep(ms) {
console.log('123213xxx')
return new Promise(resolve => setTimeout(resolve, ms));
}
async function name2(params) {
throw new Error('test2');
}
name2()
sleep(1000000)
结果如下图:
加入 unhandledRejection 异常事件的捕获之后
function sleep(ms) {
console.log('123213xxx')
return new Promise(resolve => setTimeout(resolve, ms));
}
async function name2(params) {
throw new Error('test2');
}
name2()
sleep(1000000)
process.on('unhandledRejection', ()=>{
console.log('xxxxxxxxx')
// process.exit(1)
})
结果如上图: 输出了 console.log('xxxxxxxxx'), 警告日志也没有了
Node14
及以前 unhandledRejection
只能捕获异步异常, uncaughtException
只能捕获同步异常, 监听了 uncaughtException
和 unhandledRejection
则不会直接退出主进程,除非手动退出。
在Node14以后的版本unhandledRejection
还是只能捕获异步异常,但是 uncaughtException
可以同时catch同步和异步异常,当同时设置了 unhandledRejection 和 uncaughtException 时, 如果是异步的error,则只有 unhandledRejection 会监听到,uncaughtException 不会监听到。
Node14以后的版本代码示例如下
function sleep(ms) {
console.log('123213xxx')
return new Promise(resolve => setTimeout(resolve, ms));
}
async function name2(params) {
throw new Error('test2');
}
name2()
sleep(1000000)
// uncaughtException catch 到了异步任务
process.on('uncaughtException', ()=>{
console.log('xxxxxxxxx123123')
// process.exit(0)
})
当同时设置了 unhandledRejection 和 uncaughtException 时, 异步的error,则只有 unhandledRejection 会监听到,uncaughtException 不会监听到。
function sleep(ms) {
console.log('123213xxx')
return new Promise(resolve => setTimeout(resolve, ms));
}
async function name2(params) {
throw new Error('test2');
}
name2()
sleep(1000000)
process.on('unhandledRejection', ()=>{
console.log('xxxxxxxxx')
// process.exit(1)
})
process.on('uncaughtException', ()=>{
console.log('xxxxxxxxx123123')
// process.exit(0)
})
throw new Error('test2');
延展:
有些服务可能会自己做优雅重启,会在代码了同时设置unhandledRejection
和 uncaughtException
的监听时,出现异常时重启服务,一般会在回调加入一些释放资源的操作,比如关闭数据库的连接,关闭http的连接
等,但是这里要注意,如果在高并发的情况下,两个事件如果同时正在处理,要注意判断上述的资源是否已经关闭/释放,再决定执行代码,不然关闭/释放两次可能会导致报错。
更好的处理是,对于 Node14
以后的版本,只设置 uncaughtException
的监听,就不会出现多个事件同时执行的情况了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。