NodeJS:如何在Promise循环中返回MySQL查询结果?
问题分析与解决方案
你的问题出在两个关键地方:没有等待异步查询完成,以及把普通对象而非Promise放进了promiseArray,导致Promise.all直接返回了原始的事件对象,根本没等到成员查询的结果。
修复步骤
1. 确保数据库查询返回Promise
首先要确认你的db.query是否支持Promise。如果是传统的回调式API(比如mysql模块的默认query方法),需要先把它转成Promise风格:
// 用Node.js内置的util模块来promisify const util = require('util'); // 替换原有的query方法为Promise版本 db.query = util.promisify(db.query);
如果不想修改原方法,也可以自己封装一个Promise版的查询函数:
function getMembersQuery(sql) { return new Promise((resolve, reject) => { db.query(sql, (err, results) => { if (err) return reject(err); resolve(results); }); }); }
2. 重构循环逻辑,正确收集Promise
原来的代码直接把element对象塞进了数组,而我们需要的是每个事件对应的查询Promise——等查询完成后,把成员结果赋值给事件对象,再返回这个对象。
修改后的代码(用forEach的写法):
const promiseArray = []; rows.forEach(element => { // 为每个事件创建一个查询Promise(注意替换成对应事件的查询参数,比如WHERE event_id = ?) const memberPromise = db.query("你的MySQL查询语句", [element.id]) .then(members => { // 查询完成后,把成员结果赋值给事件对象 element.members = members; // 返回更新后的事件对象 return element; }); // 把Promise加入数组 promiseArray.push(memberPromise); }); // 等待所有查询完成后返回结果,别忘了处理错误! Promise.all(promiseArray) .then(data => { response.send({ data: data }); }) .catch(err => { response.status(500).send({ error: err.message }); });
如果想更简洁,可以用map方法直接生成Promise数组:
const promiseArray = rows.map(element => { return db.query("你的MySQL查询语句", [element.id]) .then(members => { element.members = members; return element; }); }); Promise.all(promiseArray) .then(data => response.send({ data })) .catch(err => response.status(500).send({ error: err.message }));
为什么原来的代码不行?
- 你把
element对象直接放进了promiseArray,而不是异步查询的Promise。Promise.all遇到非Promise的元素会直接把它当成已resolve的值,所以根本不会等待查询完成。 element.members = db.query(...)赋值的是查询方法的返回值(通常是一个查询请求对象,不是结果),因为查询是异步的,这行代码执行时查询还没结束,结果还没出来。
内容的提问来源于stack exchange,提问作者Monika Mni
相关产品推荐
相关产品推荐

