NodeJS结合MySQL开发时map回调push对象后数组为空问题咨询
问题排查与修复方案
根本原因
- Node.js环境下的
conn.query是异步非阻塞接口,回调函数会等数据库IO操作完成后才触发执行 - 原有代码中的
console.log和res.send是同步执行逻辑,运行时机早于所有查询回调的触发时间,此时userTasklist还没有被写入任何数据 map遍历只是同步发起了所有查询请求,没有等待所有请求执行完成就返回了结果,因此拿到的是空数组
修复方案
方案1:async/await写法(更推荐,逻辑更清晰)
首先使用mysql2的promise版本API,重写代码如下:
// 引入mysql2的promise版本 const mysql = require('mysql2/promise'); // 确保conn是mysql2/promise创建的连接或连接池 exports.allUserList = async (req, res) => { try { const userID = req.params.userid; const ghusersQuery = "SELECT user_id, name, employee_code FROM users WHERE under_gh = ?"; const [userdata] = await conn.query(ghusersQuery, [userID]); if (!userdata || userdata.length === 0) { return res.send({ message: "Data not found!" }) } // 等待所有用户的任务查询完成 const userTasklist = await Promise.all( userdata.map(async (datauser) => { const userDataQuery = "SELECT * FROM tasklist WHERE user_id = ?"; const [taskdata] = await conn.query(userDataQuery, [datauser.user_id]); if (taskdata && taskdata.length > 0) { return { userid: datauser.user_id, tasklist: taskdata } } return null; }) ) // 过滤掉没有任务的空项 const finalTaskList = userTasklist.filter(Boolean); console.log(finalTaskList) res.send({ message: "user list fetched", userdata: userdata, tasklistdata: finalTaskList }) } catch (err) { res.send({ message: err }) } }
方案2:回调计数写法(兼容原有回调逻辑)
如果不想调整为promise写法,可以通过计数器判断所有请求完成后再返回结果:
exports.allUserList = (req, res) => { const userID = req.params.userid; const ghusersQuery = "SELECT user_id, name, employee_code FROM users WHERE under_gh = ?"; conn.query(ghusersQuery, [userID], (err, userdata) => { if (err) { return res.send({ message: err }) } if (!userdata || userdata.length === 0) { return res.send({ message: "Data not found!" }) } const userTasklist = []; let completedCount = 0; const totalCount = userdata.length; userdata.forEach((datauser) => { const userDataQuery = "SELECT * FROM tasklist WHERE user_id = ?"; conn.query(userDataQuery, [datauser.user_id], (errnew, taskdata) => { completedCount++; if (taskdata && taskdata.length > 0) { userTasklist.push({ userid: datauser.user_id, tasklist: taskdata }); } // 所有查询执行完成后再打印和返回响应 if (completedCount === totalCount) { console.log(userTasklist) res.send({ message: "user list fetched", userdata: userdata, tasklistdata: userTasklist }) } }) }) }) }
内容的提问来源于stack exchange,提问作者Ankit
相关产品推荐
相关产品推荐

