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)

结果如下图:
image.png

加入 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)
})

image.png

结果如上图: 输出了 console.log('xxxxxxxxx'), 警告日志也没有了

Node14及以前 unhandledRejection 只能捕获异步异常, uncaughtException 只能捕获同步异常, 监听了 uncaughtExceptionunhandledRejection则不会直接退出主进程,除非手动退出。

在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)
})

image.png

当同时设置了 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');

image.png

延展:

有些服务可能会自己做优雅重启,会在代码了同时设置unhandledRejectionuncaughtException 的监听时,出现异常时重启服务,一般会在回调加入一些释放资源的操作,比如关闭数据库的连接,关闭http的连接等,但是这里要注意,如果在高并发的情况下,两个事件如果同时正在处理,要注意判断上述的资源是否已经关闭/释放,再决定执行代码,不然关闭/释放两次可能会导致报错。

更好的处理是,对于 Node14以后的版本,只设置 uncaughtException 的监听,就不会出现多个事件同时执行的情况了。


神话
1.6k 声望37 粉丝

编程使我快乐!Node.js excel处理库 @zurmokeeper/exceljs 支持读取加密excel和导出加密excel,支持多表头excel快捷导出