如何在JavaScript map中同步执行MySQL INSERT语句 解决异步结果为空问题
问题根源
你碰到的现象是JS异步遍历的经典踩坑,核心是对Array.map()和async/await的配合逻辑存在认知偏差:
anArray.map(async o => {...})的执行是纯同步遍历:会立刻跑完所有遍历的同步逻辑,把每个async回调返回的Promise收集起来,生成一个普通的Promise数组返回,根本不会等回调内部的await异步操作完成- 你直接给这个普通Promise数组加await时,await的规则是:如果后面跟的值不是Promise,会直接把这个值原样返回,根本不会去等数组内部的每个Promise执行完
- 所以代码执行流会直接跳过等待,走到
console.log(resultMap)这行,此时所有MySQL插入的异步任务还在事件队列里没执行,自然打印的是空数组;等后续异步任务被事件循环调度执行时,才会依次触发push操作,打出后续的----> pushed日志。
解决方案
方案1:并行执行插入(性能优先,无顺序要求时使用)
用Promise.all()包裹map返回的Promise数组,等待所有插入操作全部完成后再继续执行后续逻辑,而且可以直接从Promise.all的返回值拿到所有插入结果,不需要手动操作push,可靠性更高:
const resultMap = await Promise.all( anArray.map(async (o) => { // 直接返回查询结果,会被Promise.all自动收集成完整的结果数组 return await connection.query('insert into (...) values (...)', [...]); }) ); // 这行日志会在所有插入完成后才执行,resultMap就是完整的结果集 console.log(resultMap);
注意:并行执行时需要确保MySQL连接池的容量足以支撑并发插入数,否则会出现连接超时、任务排队的问题。
方案2:串行顺序执行(需要严格按原数组顺序逐条插入、避免并发问题时使用)
用for...of循环替代map,每次循环都等待上一次插入完成后再执行下一次操作,全程保持同步执行顺序:
const resultMap = []; for (const o of anArray) { // 等待单条插入完成,把结果推入数组 const result = await connection.query('insert into (...) values (...)', [...]); resultMap.push(result); } // 所有插入按顺序全部完成后才会执行这行 console.log(resultMap);
注意:串行执行的总耗时是所有单条插入的时间累加,适合小批量插入、对执行顺序有强依赖的场景。
原代码的其他疏漏
你代码里写的console.log('----> pushed', ) 存在语法小问题:第二个参数位置留空没有传入实际要打印的result值,就算异步执行逻辑正常,打印出来的内容也是不完整的。
内容的提问来源于stack exchange,提问作者nightograph
相关产品推荐
相关产品推荐

