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
相关产品推荐
相关产品推荐

