NodeJS async函数抛出异常触发unhandledRejection而非uncaughtException原因问询
问题成因说明
首先明确两个Node.js全局异常捕获事件的触发边界:
uncaughtException仅捕获同步代码执行链路中没有被try/catch捕获的同步异常unhandledRejection捕获没有通过catch方法/await try/catch处理的Promise拒绝状态
你遇到的问题核心是async函数的内置异常封装机制,具体链路如下:
- 你定义的
MainAwait是async函数,按照ECMAScript规范,所有async函数的返回值都会被自动封装为Promise对象:如果函数内部抛出未被捕获的异常,这个异常不会作为同步异常向上穿透,而是会直接让返回的Promise变为rejected状态。 - 代码执行时的抛错流程:
- 第一次调用
ConfigHandlerObj.load(szConfigFilename)时,目标配置文件不存在,fs.readFileSync同步抛出异常,被外层的try/catch正常捕获 - catch分支中你再次调用了
ConfigHandlerObj.load(szConfigFilename),这次调用依然会触发同步抛错,但此时catch块内没有嵌套try/catch来捕获这个异常 - 这个未被捕获的异常出现在async函数内部,被自动封装为
MainAwait()返回的Promise的rejection原因
- 第一次调用
- 你调用
MainAwait()时,既没有跟上.catch()处理拒绝状态,也没有用await包裹后在外层加try/catch处理异常,所以这个未处理的Promise拒绝就触发了process.on('unhandledRejection')事件,不会走到同步异常的uncaughtException捕获逻辑。
验证方案
你可以通过两个简单修改验证上述结论:
- 方案1:调用
MainAwait()时添加catch处理,修改为MainAwait().catch(err => console.log('捕获到Promise拒绝', err)),就不会再触发unhandledRejection事件 - 方案2:删除
MainAwait的async关键字改为普通函数,未捕获的同步异常就会触发uncaughtException事件,符合你的初始预期。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

