Node.js中无法将SQL查询结果推入数组的问题求助
问题根源
- 你的代码用的是回调式数据库查询,所有
connection.query都是异步执行的——外层代码不会等这些查询完成就继续执行,等你想访问data数组时,里面的push操作大概率还没全部跑完,所以看起来像是没生效。 - 另外
forEach里加async完全没用,forEach根本不会等待异步函数执行完毕,会直接遍历完所有referer,剩下的查询全在后台无序执行,顺序和完成时间都没法保证。
修复方案
把回调式查询改成Promise封装,用async/await控制异步流程,确保所有查询都跑完再填充data:
首先封装Promise版的查询工具函数:
function query(sql, params) { return new Promise((resolve, reject) => { connection.query(sql, params, (err, results) => { err ? reject(err) : resolve(results); }); }); }
然后重写业务逻辑:
async function getHourlyData() { const data = []; try { // 先获取所有唯一的referer const refererList = await query("SELECT DISTINCT referer FROM publisher"); // 用for...of遍历,配合await确保每个referer的查询按顺序完成 for (const item of refererList) { const referer = item.referer; const today = new Date(); for (let hour = 0; hour < 24; hour++) { const start = new Date(today); start.setHours(hour, 0, 0, 0); const end = new Date(today); end.setHours(hour, 59, 59, 999); // 等待当前小时的统计结果返回 const countRes = await query( "SELECT COUNT(*) AS count FROM publisher WHERE referer = ? AND first_seen >= ? AND first_seen <= ?", [referer, start, end] ); data.push({ referer, hour, count: countRes[0].count }); } } // 到这里所有数据都已填充完成,可以直接使用 console.log(data); return data; } catch (err) { console.error("查询出错:", err); } } // 调用函数获取数据 getHourlyData();
性能优化建议
你当前的逻辑要执行1 + N*24次查询(N是referer的数量),数据量大时数据库压力会很大。可以直接用一次SQL查询搞定所有统计,效率提升明显:
SELECT referer, HOUR(first_seen) AS hour, COUNT(*) AS count FROM publisher WHERE DATE(first_seen) = CURDATE() GROUP BY referer, HOUR(first_seen) ORDER BY referer, hour;
拿到查询结果后再整理成你需要的数组格式即可,无需循环24次查询。
内容的提问来源于stack exchange,提问作者Bu Fahad
相关产品推荐
相关产品推荐

