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

NodeJS+MySQL中async/await未等待MySQL查询完成的问题排查

问题分析与修复方案

你的代码里主要有三个关键问题导致await/async没有正确等待MySQL查询完成,和MySQL超时时间关系不大,咱们一步步拆解:

1. sqlPushSteamappid 函数未正确结束Promise状态

你在这个函数里创建了Promise,但查询完成后既没有调用res()(成功时)也没有调用rej()(失败时),导致Promise一直处于pending状态。await这个Promise的时候自然永远等不到结果,而且后续的批量插入也没法确认是否执行完成。

2. 批量调用sqlPushSteamappid时未等待所有插入完成

你用for循环直接调用sqlPushSteamappid(gameList[i])却没加await,这会让所有插入请求同时发出去,但主线程不等它们全部完成就直接执行sqlGetSteamNames()。这时候数据库里的插入操作可能还没跑完,查询自然拿不到完整的数据。

3. sqlGetSteamNames 函数返回的是Promise而非实际查询结果

你在函数里await tmp之后,返回的还是tmp(也就是Promise对象),而不是await tmp得到的查询结果,这会导致调用方拿到的不是想要的数据,而是一个未处理的Promise。


修正后的代码

修复sqlPushSteamappid函数

async function sqlPushSteamappid(appId){ 
  return new Promise((res, rej) => { 
    // 注意:这里改用参数化查询,避免SQL注入风险
    let sql='INSERT INTO cleetusbot.tmp (appId) VALUES (?);'; 
    global.pool.query(sql, [appId], function (err, results, fields) { 
      if(err){ 
        console.log(err);
        rej(err); // 出错时主动reject Promise
        return;
      } 
      res(results); // 成功时resolve Promise,返回插入结果
    }); 
  }); 
}

额外提醒:直接把appId拼进SQL字符串有SQL注入风险,用参数化查询(把变量放到数组里传给query)是MySQL官方推荐的安全写法。

修复批量插入的调用逻辑

确保所有插入完成后再执行查询,有两种方式可选:

// 方法1:用Promise.all并行执行(效率更高,适合无顺序要求的场景)
await Promise.all(gameList.map(appId => sqlPushSteamappid(appId)));

// 方法2:逐个串行执行(适合需要按顺序插入的场景)
for(let i = 0; i < gameList.length; i++){ 
  await sqlPushSteamappid(gameList[i]); 
}

修复sqlGetSteamNames函数

async function sqlGetSteamNames(){ 
  return new Promise((res, rej) => { 
    let sql='SELECT * FROM cleetusbot.steamGames INNER JOIN tmp ON cleetusbot.steamGames.appId = cleetusbot.tmp.appId;'; 
    global.pool.query(sql,function (err, results, fields) { 
      if(err){ 
        console.log(err);
        rej(err);
        return;
      } 
      res(results); // 直接把查询结果resolve出去
    }); 
  }); 
}

// 现在调用就能拿到实际的查询结果了
let steamNameObj = await sqlGetSteamNames();

也可以写成更简洁的async/await嵌套形式:

async function sqlGetSteamNames(){ 
  try {
    const sql='SELECT * FROM cleetusbot.steamGames INNER JOIN tmp ON cleetusbot.steamGames.appId = cleetusbot.tmp.appId;'; 
    const results = await new Promise((res, rej) => {
      global.pool.query(sql, (err, results) => err ? rej(err) : res(results));
    });
    return results;
  } catch (err) {
    console.log(err);
    throw err; // 把错误抛出去让调用方处理
  }
}

总结

这些修改后,你的代码就能正确等待MySQL查询完成了:

  • 每个Promise都会在查询完成后明确结束状态(resolve/reject)
  • 批量操作时确保所有插入完成后再执行后续查询
  • 函数返回的是实际的查询结果而非Promise对象

内容的提问来源于stack exchange,提问作者James Obrien

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 20:32:28