Node.js中调用两个异步函数用Await未返回预期值及超时需求
问题分析
- 结果集被修改/耗尽:
getData中修改了resultset内部的rs.rows属性(将迭代器替换为数组),同时部分数据库驱动的结果集是一次性迭代资源,遍历后无法再次读取,导致后续convertToArray调用时无法获取数据,返回undefined。 - Promise反模式:
exec和gues函数存在不必要的new Promise包裹——async函数本身已返回Promise,这种写法会增加代码复杂度和潜在异常。 - 参数传递缺失:原
gues函数未接收resultset参数,调用exec时会传入未定义变量,直接导致执行失败。 - 缺少超时控制:未实现2分钟超时逻辑,无法在执行超时时主动抛出错误。
解决方案
1. 缓存结果集,避免重复消费/修改原对象
先将结果集转换为数组缓存,再基于缓存数据执行后续逻辑,彻底解决结果集被耗尽或修改的问题。
2. 移除Promise反模式,简化异步代码
利用async函数的原生特性,直接返回异步操作结果,无需额外包裹new Promise。
3. 实现超时控制
通过Promise.race将业务逻辑与超时Promise结合,达到2分钟自动报错的需求。
修改后的完整代码
重构工具函数(基于缓存数组操作)
// 重构getData:直接使用缓存的数组,避免修改原resultset function getData(rows) { console.log(rows.length); return Promise.resolve(rows); } // 保留convertToArray核心逻辑:负责将原resultset转为数组缓存 function convertToArray(resultset) { return new Promise((resolve, reject) => { resultset.toObjArray(function (err, results) { if (err) { reject(err); } else { resolve(results); } }); }); }
重构exec函数(添加超时+复用缓存)
function exec(resultset) { // 定义2分钟超时Promise(120000毫秒) const timeoutPromise = new Promise((_, reject) => { setTimeout(() => { reject(new Error("exec函数执行超时,已超过2分钟")); }, 120000); }); // 业务逻辑:先缓存数组,再依次执行两个函数 const businessLogic = async () => { const cachedRows = await convertToArray(resultset); await getData(cachedRows); // 执行getData逻辑 return cachedRows; // 返回最终需要的结果 }; // 用Promise.race实现超时控制 return Promise.race([timeoutPromise, businessLogic()]); }
重构gues函数(修复参数传递+简化逻辑)
exports.gues = async function (resultset) { try { return await exec(resultset); } catch (err) { throw err; } };
补充说明
- 如果必须保留原
getData对resultset的修改逻辑,建议先克隆resultset再传入(部分数据库驱动支持结果集克隆),避免修改原对象影响后续调用。 - 若
getData和convertToArray逻辑存在重复,可合并为一个函数减少冗余。
内容的提问来源于stack exchange,提问作者Hans Query
相关产品推荐
相关产品推荐

