Node.js Web API async/await循环不等待致total_json为空问题求解
问题核心根因
你当前搭的Promise.all + async/await结构完全没起到等待作用,本质踩了Node.js异步场景最常见的坑:循环里嵌套的COMMON是老的回调风格异步接口,根本没有被包装成Promise。map里的async函数执行到COMMON(...)调用时,注册完回调就立刻返回了resolved状态,根本不会等回调真正执行完成。这就导致Promise.all刚接收到所有map返回的“空Promise”,就判定任务全部结束,直接往下走到console.log语句——这时候所有COMMON的回调还没执行,total_json自然还是最开始的空数组。
针对性改造实现
1. 先将回调式查询方法封装为可await的Promise
这一步是整个改造的核心——只有把回调的成功/失败和Promise的resolve/reject绑定,async函数才会真正暂停等待查询完成,而不是提前返回。
// 封装Promise版本的分类查询方法 const getVoucherCategory = (cateId) => { return new Promise((resolve, reject) => { const reqParams = { ...body, query: `select * from tb_voucher_category where id = '${cateId}'` }; COMMON(reqParams, (err, queryRes) => { if (err) return reject(err); resolve(queryRes); }) } }
2. 重构循环逻辑,移除共享数组的手动push操作
避免闭包操作外部共享变量带来的时序混乱,让每个async迭代函数直接返回组装好的对象,由Promise.all最终生成完整数组:
let total_json = []; // 先过滤符合日期匹配规则的元素,减少无效循环 const validList = results.filter(ele => ele.start_date <= d && ele.end_date >= d ); try { // 直接接收Promise.all返回的完整数组,不需要手动往外部共享数组push total_json = await Promise.all(validList.map(async (element) => { // 直接await查询结果,async函数会在这里暂停等待,不会提前返回 const categoryRes = await getVoucherCategory(element.cateID); // 处理分类名称 let cateName = categoryRes.length > 0 ? categoryRes[0].cateName : ''; // 直接返回组装好的对象 return { id: element.id, catename: cateName, title: element.title, description: element.description, expired_date: element.expired_date, expired_time: element.expired_time, vStatus: element.vStatus } })); } catch (err) { // 补全错误捕获,替换原来在回调里写的错误返回逻辑 fatal_error.data = err; return res.json(fatal_error); } // 这里打印时,total_json已经是所有异步查询完成后的完整数据 console.log(total_json)
补充说明:如果不想手动封装Promise版本的查询方法,可以直接用Node.js内置的
util.promisify方法,将回调风格的COMMON快速转换为Promise版本。
内容的提问来源于stack exchange,提问作者Joel_Abraham
相关产品推荐
相关产品推荐

