You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:05:28