NestJS+Mongoose项目中forEach循环后数组为空问题排查
问题分析与解决方案
错误原因
forEach是同步遍历方法,它不会等待内部的异步函数执行完成。当外部的console.log(updatedItems)执行时,循环里所有的异步操作(await调用的数据库方法)都还没完成,所以数组还是空的。- 循环内部的
console.log能打印数据,是因为它在两次await之后执行,此时当前迭代的异步任务已经完成,数据已经被push进数组。
修复方案
方案一:使用 for...of 循环(顺序执行)
for...of 支持异步等待,会逐个执行并等待每个异步任务完成后再进入下一次循环:
const updatedItems: Item[] = []; for (const purchasedItem of purchaseData.items) { const itemInDB = await this.itemService.findItemByName(purchasedItem.name); itemInDB.quantity -= purchasedItem.quantity; const updatedItem = await this.itemService.updateItem(itemInDB['_id'], itemInDB); updatedItems.push(updatedItem); } console.log(updatedItems); // 此时能拿到完整的更新后数据
方案二:使用 Promise.all 结合 map(并行执行)
如果你的商品更新操作之间没有依赖关系,可以用这种方式并行处理,效率更高:
const updatedItems = await Promise.all( purchaseData.items.map(async (purchasedItem) => { const itemInDB = await this.itemService.findItemByName(purchasedItem.name); itemInDB.quantity -= purchasedItem.quantity; return this.itemService.updateItem(itemInDB['_id'], itemInDB); }) ); console.log(updatedItems); // 直接获取所有更新后的结果数组
注意事项
- 顺序执行适合有依赖的场景(比如前一个商品的更新会影响后一个的计算),但速度较慢;
- 并行执行效率更高,但要注意数据库的并发压力,避免短时间内发起过多请求。
内容的提问来源于stack exchange,提问作者Tony Stark
相关产品推荐
相关产品推荐

