使用async/await捕获异常时触发unhandledRejection的问题排查与解决
问题解答
1. 为何try/catch无法捕获该异常?
throwFunction是async函数,它内部抛出的错误会被自动包装成rejected状态的Promise返回。- 你调用
throwFunction()时没有用await,也没给这个返回的Promise绑定任何错误处理(比如.catch()),这个Promise就成了“无主”的rejected Promise。 - async函数里的
try/catch仅能捕获两类错误:- 同步执行代码抛出的错误
- 被
await的Promise的rejection
- 此处
throwFunction()返回的Promise既没被await,也没接入错误处理链,它的rejection不在当前try/catch的处理范围内,最终触发全局的unhandledRejection事件。
2. 如何修复此问题?
根据你“不等待throwFunction完成,同时捕获异常”的需求,提供两种可行方案:
方案一:直接给throwFunction的Promise绑定.catch()
无需修改执行流程,直接处理它的异常:
const setTimeout = require ('timers/promises').setTimeout; async function waitALittle(){ await setTimeout(100); } async function throwFunction(a){ //do some stuff... throw new Error('test'); } async function f(){ try { // 给throwFunction返回的Promise绑定catch处理异常 throwFunction().catch(e => { console.log('exception caught from throwFunction'); }); console.log('wait started') await waitALittle(); console.log('wait ended') }catch(e) { console.log('exception caught in main try/catch'); } } process.on('unhandledRejection', ()=>{ console.log('unhandledRejection event'); }) f();
该方案下,throwFunction的异常会被自身的.catch()捕获,不会触发全局unhandledRejection,同时waitALittle会正常执行,无需等待throwFunction完成。
方案二:延后处理throwFunction的Promise状态
如果需要在后续流程中处理throwFunction的结果,可以先保存它的Promise实例,之后再处理:
const setTimeout = require ('timers/promises').setTimeout; async function waitALittle(){ await setTimeout(100); } async function throwFunction(a){ //do some stuff... throw new Error('test'); } async function f(){ try { // 保存throwFunction的Promise实例 const throwTask = throwFunction(); console.log('wait started') await waitALittle(); console.log('wait ended'); // 延后处理throwFunction的异常 const result = await throwTask.catch(e => e); if(result instanceof Error){ console.log('caught throwFunction error later:', result.message); } }catch(e) { console.log('exception caught in main try/catch'); } } process.on('unhandledRejection', ()=>{ console.log('unhandledRejection event'); }) f();
这种方式既不会阻塞waitALittle的执行,也能在合适时机处理throwFunction的异常,同样不会触发unhandledRejection。
内容的提问来源于stack exchange,提问作者ryan
相关产品推荐
相关产品推荐

