NodeJS forEach内使用await未等待异步执行问题排查
问题核心原因
你的异步逻辑未按预期等待的问题,确实由forEach的错误使用导致:
Array.prototype.forEach本身没有返回值(返回undefined),不会感知、也不会等待传入的异步回调执行完成- 你在
forEach前添加的await完全不生效,因为await拿到的是undefined,相当于执行完forEach的同步调度逻辑后,就会直接继续执行外层后续代码,根本不会等待循环内的数据库存储操作结束 - forEach执行时只会同步把所有异步回调注册到任务队列,之后就立刻往下走,所以你会看到外层逻辑的日志(10、12、14、15)先打印,等事件循环轮到异步存储任务执行完成后,才会打印循环内的13、存储操作相关的11日志,和你观测到的现象完全一致。
修复方式
根据你需要的执行策略二选一即可:
方案1:串行执行(数据库操作优先选这个,避免并发过高打满连接)
用原生for...of循环替换forEach,循环内的await会正常等待每一个异步操作执行完成后,再进入下一轮循环:
async addResponsesToTasks(input, response, isFromCache) { if (!isFromCache) { // 注意:如果saveResponseToCache是异步函数,这里也需要加await,否则同样会出现不等待的问题 this.saveResponseToCache(input, response); } console.log("===7==="); for (const pokemon of response) { console.log("===8===", pokemon); await this.addTaskToFile(pokemon, false); console.log("===13==="); } return true; }
方案2:并行执行(适合数据量小、追求执行速度的场景)
用Array.prototype.map配合Promise.all,map会把每个异步回调返回的Promise收集成数组,Promise.all会等待所有并行执行的异步操作全部完成后,再继续往下走:
async addResponsesToTasks(input, response, isFromCache) { if (!isFromCache) { this.saveResponseToCache(input, response); } console.log("===7==="); await Promise.all(response.map(async (pokemon) => { console.log("===8===", pokemon); await this.addTaskToFile(pokemon, false); console.log("===13==="); })); return true; }
补充提醒:所有返回Promise的异步函数调用,如果需要等待执行完成再走后续逻辑,都必须搭配await,不要漏加。
内容的提问来源于stack exchange,提问作者Avr.Nadav
相关产品推荐
相关产品推荐

