Node12.x AWS Lambda中try-catch无法捕获Promise拒绝问题咨询
解决AWS Lambda升级Node.js 12.x后TimeoutError无法被try-catch捕获的问题
我之前升级Node.js版本时也碰到过一模一样的问题,这本质是Node.js版本迭代后对Promise未处理拒绝的机制变严格了,加上AWS SDK的Promise行为在新版本下的小变化导致的。
问题根源
在Node.js 8.10中,未处理的Promise拒绝只会触发警告,不会直接终止进程;但从Node.js 10.x开始,未处理的Promise拒绝会被视为致命错误,直接终止运行(包括Lambda函数)。
你的代码里,当你把lambda.invoke(params).promise()推到数组后,这个Promise可能在你还没轮到await它的时候就已经因为超时拒绝了——这时候还没进入try-catch块,所以这个拒绝就变成了“未处理的Promise拒绝”,直接触发Lambda终止。
解决方案
有两种简单有效的处理方式,选哪种都可以:
方式1:提前给每个Promise包装错误捕获
在把Promise加入数组时,就用.catch()捕获所有可能的错误,将Promise转化为永远resolve的状态,返回包含成功/失败标记的对象:
// 修改添加Promise的代码 promiseArray.push( lambda.invoke(params).promise() .then(result => ({ isSuccess: true, data: result })) .catch(error => ({ isSuccess: false, error: error })) );
然后遍历的时候就不需要try-catch了,直接判断结果:
for (let i = 0; i < promiseArray.length; i++) { const result = await promiseArray[i]; if (result.isSuccess) { console.log("Success!"); } else { console.log("Failed!", result.error); } }
方式2:使用Promise.allSettled(Node.js 12.x原生支持)
这个方法会等待所有Promise完成(不管成功还是失败),返回每个Promise的状态结果,完美适配批量处理场景:
// 直接批量处理所有Promise const results = await Promise.allSettled(promiseArray); // 遍历结果处理 results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`Promise ${index} Success!`); } else { console.log(`Promise ${index} Failed!`, result.reason); } });
额外提醒
如果你的Lambda函数还会处理其他Promise,最好全局添加一个未处理拒绝的监听器作为兜底(虽然上面的方案已经能解决问题,但多一层保障更稳妥):
process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); // 这里可以添加自定义的兜底处理逻辑 });
内容的提问来源于stack exchange,提问作者spoderman
相关产品推荐
相关产品推荐

