嵌套函数中Promise rejection如何捕获 避免Node.js报unhandledRejection错误
问题原因
你遇到的unhandledRejection报错核心有两个:
- async 函数的
try/catch只能捕获被await的Promise抛出的错误,你当前代码注释了await promise的逻辑,Promise reject的错误无法被外层try/catch捕获。 - 你当前的
try块只包裹了同步执行的waitBy(3000)调用,这个调用只会同步返回包含promise和cancel的对象,不会抛出任何错误,所以现有写的catch逻辑永远不会触发。
没有被任何错误处理逻辑捕获的Promise reject,就会被Node.js判定为未处理的拒绝,默认会直接终止进程。
解决方案
如果要让错误正常冒泡到main函数的catch块,只需要把await promise移入同一个try块内即可,修正后的代码如下:
const wait = (timeoutMs: number) => { let timeoutHandle: number | undefined; const promise = new Promise((_resolve, reject) => { timeoutHandle = setTimeout(() => { reject(`wait timed out after ${timeoutMs} ms`); }, timeoutMs); }); return { promise, cancel: (): void => clearTimeout(timeoutHandle) }; }; const waitBy = (timeoutMs: number) => { const res = wait(timeoutMs); return res; }; const main = async () => { try { const { promise, cancel } = waitBy(3000); // 新增await逻辑,放在同一个try块内 await promise; } catch (error) { console.log("timed out", error); } }; main();
特殊场景兼容
如果你需要先拿到cancel句柄做其他操作,暂时不需要等待Promise结果,可以临时给Promise挂载一个空的catch回调避免报错,等需要的时候再await原Promise即可,写法如下:
const main = async () => { try { const { promise, cancel } = waitBy(3000); // 临时挂载catch避免未处理拒绝报错,不会影响后续await的错误捕获 promise.catch(() => {}); // 这里可以放其他逻辑,比如3秒内调用cancel就可以取消超时 // cancel() await promise; } catch (error) { console.log("timed out", error); } };
注意这种写法只是临时兜底避免进程崩溃,最终错误还是会被await后的try/catch正常捕获,不会丢失错误信息。
内容的提问来源于stack exchange,提问作者benhowdle89
相关产品推荐
相关产品推荐

