为什么在mysql的connection.query上使用await未达到同步效果?
错误原因
Array.prototype.forEach不支持异步函数串行执行,传入的async回调会被并发触发,不会等待前一个回调内的await执行完成再执行下一个,因此所有nr日志会先批量打印,之后才陆续返回查询结果。- 直接await callback形式的
connection.query无效,callback风格的API返回值不是Promise,await仅对Promise类型生效。 - 自定义的
queryPromise存在语法错误:if(err)分支结构书写错误,导致reject逻辑无论是否报错都会执行;Promise构造函数前缀的async属于冗余写法,没有实际作用。
修复方案
1. 修正queryPromise封装
const queryPromise = ( connection: Connection, query: string, value: (string | number) [] ) => { return new Promise((resolve, reject) => { connection.query(query, value, function (err, result) { if (err) { console.log("err: ", err, " result: ", result); return reject(err); } return resolve(result); }); }); }
2. 替换forEach为支持异步串行的for...of循环
如果需要按用户顺序逐个执行查询(前一个查询结束后再执行下一个),使用如下写法(注意await必须放在async函数内部):
let users: number [] = [1, 2, 3] async function runSerialQueries() { for (const usernr of users) { console.log("nr:" + usernr) try { // 用参数占位符?传值,避免SQL注入风险,不要直接拼接SQL字符串 const result = await queryPromise(connection, "select count(*) from documents where userid = ?", [usernr]) console.log("result: ", result, " nr: ", usernr); } catch (err) { console.log("err: ", err, " nr: ", usernr); } } } runSerialQueries()
执行后输出为预期的串行结果:
nr:1 result: [ RowDataPacket { 'count(*)': 10 } ] nr: 1 nr:2 result: [ RowDataPacket { 'count(*)': 20 } ] nr: 2 nr:3 result: [ RowDataPacket { 'count(*)': 30 } ] nr: 3
3. 可选:并行查询统一处理结果
如果不需要严格按顺序执行,仅需要所有查询完成后统一处理结果,可使用Promise.all提升执行效率:
async function runParallelQueries() { const queryTasks = users.map(async usernr => { const result = await queryPromise(connection, "select count(*) from documents where userid = ?", [usernr]) return { usernr, result } }) const allResults = await Promise.all(queryTasks) allResults.forEach(({usernr, result}) => { console.log("result: ", result, " nr: ", usernr) }) } runParallelQueries()
内容的提问来源于stack exchange,提问作者Gerd
相关产品推荐
相关产品推荐

