Node.js MVC项目连接MySQL查询返回undefined问题排查
问题根源:异步操作的返回值无法同步获取
嘿,这个问题我太熟悉了——你踩中了Node.js异步操作的经典坑!咱们一步步拆解问题:
你的getAllUsers函数里,con.connect和con.query都是异步函数,它们不会阻塞代码执行,而是在后台完成操作后调用传入的回调函数。当你在控制器里调用var arr = UserModel.getAllUsers()时,getAllUsers会立刻执行完毕并返回undefined(因为你没有在函数最外层写return语句),而数据库查询的结果要等回调函数触发时才会生成——这时候控制器早就已经执行完res.send(arr)了,所以arr自然是undefined。
更关键的是:你在回调函数里写的return result,只是把值返回给了回调函数的调用者(也就是MySQL驱动),根本不会把值传递给外层的getAllUsers函数。
解决方案:用回调/Promise/async-await处理异步
方法1:使用回调函数(最基础的异步处理方式)
先修改模型代码,接受一个回调函数作为参数,在查询完成后通过回调传递结果或错误:
exports.getAllUsers = function (callback) { con.connect(function (err) { if (err) { console.log('连接数据库出错:', err); // 把错误传给回调 callback(err, null); } else { con.query("SELECT * FROM Users", function (err, result, fields) { if (err) { console.log('查询出错:', err); callback(err, null); } else { // 把查询结果传给回调 callback(null, result); } }); } }); }
然后在控制器里通过回调获取结果:
exports.get_all_users = function (req, res) { UserModel.getAllUsers(function(err, arr) { if (err) { // 处理错误,返回500状态码 return res.status(500).send('数据库查询失败'); } // 成功获取结果,返回给客户端 res.send(arr); }); }
方法2:使用Promise + Async/Await(更现代、易读的方式)
回调嵌套多了容易陷入“回调地狱”,用Promise和async/await可以让代码更像同步逻辑:
先把模型改成返回Promise:
exports.getAllUsers = function () { return new Promise((resolve, reject) => { con.connect(function (err) { if (err) { console.log('连接数据库出错:', err); reject(err); // 抛出错误 } else { con.query("SELECT * FROM Users", function (err, result, fields) { if (err) { console.log('查询出错:', err); reject(err); } else { resolve(result); // 返回查询结果 } }); } }); }); }
然后在控制器里用async/await等待Promise完成:
exports.get_all_users = async function (req, res) { try { // 等待查询结果返回 const arr = await UserModel.getAllUsers(); res.send(arr); } catch (err) { // 捕获错误并处理 res.status(500).send('数据库查询失败'); console.error(err); } }
额外优化建议
你不需要每次查询都调用con.connect()——频繁建立/断开连接会影响性能。建议使用MySQL连接池,或者在应用启动时建立一次连接并复用它,这样能大幅提升数据库操作的效率。
内容的提问来源于stack exchange,提问作者Miriam H
相关产品推荐
相关产品推荐

