Node.js异步函数未等待MySQL查询响应问题求助
Node.js Express异步流程问题:await数据库查询返回undefined的解决办法
问题根源
你的checkUserInfo函数虽然标记了async,但没有返回一个有效的Promise——你在con.query的回调函数里创建了Promise,但这个Promise并没有被外层的checkUserInfo函数返回,导致函数默认返回一个状态为resolved、值为undefined的Promise,所以await拿到的结果自然是undefined。
另外还有两个潜在问题:
- 数据库连接是异步完成的,但你的服务器启动后直接处理请求,可能出现请求到达时连接还没建立的情况
- 使用字符串拼接SQL语句,存在严重的SQL注入风险
修复步骤
1. 正确封装数据库查询为Promise
把con.query包装成Promise,让checkUserInfo直接返回这个Promise,这样await就能正确获取查询结果:
// 修改dbinter.js中的checkUserInfo函数 function checkUserInfo(nameRec, passRec) { // 使用参数化查询避免SQL注入 let queryTxt = `SELECT * FROM userlogins WHERE name = ?;`; // 把con.query包装成Promise返回 return new Promise((resolve, reject) => { con.query(queryTxt, [nameRec], (err, result) => { if (err) { // 错误时reject,不要直接throw,避免进程崩溃 return reject(err); } const resultLength = Object.keys(result).length; if (resultLength === 0) { // 注意:createUser也是异步的,若需等待创建完成,也要改成Promise形式 createUser(nameRec, passRec); } console.log('query results', result); console.log('returning promise', resultLength); resolve(resultLength); }); }); }
2. 修复SQL注入风险
所有数据库操作都改用参数化查询,比如createUser函数:
// 修改dbinter.js中的createUser函数 function createUser(nameRec, passRec) { if (nameRec && passRec) { // 使用?作为占位符,避免字符串拼接 let sql = `INSERT INTO userlogins (name, password) VALUES (?, ?)`; con.query(sql, [nameRec, passRec], (err, result) => { if (err) { console.error('创建用户失败:', err); return; } console.log("creating user: " + nameRec); }); } else { console.log('name or password is null'); } }
3. 优化路由处理逻辑
把路由处理函数直接改成async,避免嵌套sendToFE函数,同时处理异步错误:
// 修改server.js中的/createuser路由 app.post("/createuser", async (req, res) => { try { const { name, password } = req.body.user[0]; const resFromSQL = await dbinter.checkUserInfo(name, password); console.log('response is:', resFromSQL); res.send({ sqlRes: resFromSQL }); } catch (err) { console.error('处理请求失败:', err); res.status(500).send({ error: '服务器内部错误' }); } });
4. 确保数据库连接完成后再启动服务器
避免请求到达时连接未建立的问题,把服务器启动逻辑放到con.connect的回调里:
// 在dbinter.js中新增获取连接的Promise函数 function getConnection() { return new Promise((resolve, reject) => { con.connect(function(err) { if (err) return reject(err); console.log("Connected!"); resolve(con); }); }); } module.exports = { getCreds, checkUserInfo, getConnection }; // 然后在server.js中等待连接完成后启动服务 dbinter.getConnection().then(() => { app.listen(PORT, () => { console.log(`Server listening on ${PORT}`); }); }).catch(err => { console.error('数据库连接失败:', err); });
修复后控制台输出顺序说明
修复后,控制台输出会变成:
Connected! Server listening on 3001 query results [object Object] returning promise 1 response is: 1
因为现在服务器会等数据库连接完成后再启动,请求处理会等待查询结果返回后再响应前端。
内容的提问来源于stack exchange,提问作者Drwooi Poipoi
相关产品推荐
相关产品推荐

