Async/Await未等待循环完成,返回空数组问题求助
问题分析与解决方案
核心问题
你的代码有三个关键问题导致输出空数组:
forEach不支持异步等待:forEach会同步遍历数组,但不会等待每个异步回调执行完成。当console.log(sortedAnimals)执行时,所有findOneAndUpdate的异步操作还没结束,数组自然为空。- 拼写错误:
ids.forEch应为ids.forEach,这个笔误会直接导致代码报错(若实际运行未报错,说明你本地代码已修正,但仍需注意这类细节)。 - 异步回调中
i的递增风险:即使forEach能等待,异步回调的执行顺序不确定,i的值可能和遍历顺序不匹配,导致order字段设置错误。
解决方案1:使用for...of循环(推荐,严格保证顺序)
for...of可以直接配合await,确保每个异步操作完成后再进行下一次循环,同时i的递增能严格对应遍历顺序:
async function getSortedAnimals() { const sortedAnimals = []; let i = 0; // 用for...of遍历,等待每个异步更新完成 for (const id of ids) { i++; const animal = await this.animalModel.findOneAndUpdate( { _id: id }, { $set: { order: i } }, // 可选:添加{ new: true },返回更新后的文档(默认返回更新前的) { new: true } ); sortedAnimals.push(animal); } console.log(sortedAnimals); return sortedAnimals; }
解决方案2:使用Promise.all(并行处理,效率更高)
如果不需要严格串行执行更新,但需要order对应数组索引,可以用Promise.all并行处理,通过数组索引设置order值:
async function getSortedAnimals() { // 用map生成所有更新操作的Promise,通过索引设置order const promises = ids.map(async (id, index) => { return await this.animalModel.findOneAndUpdate( { _id: id }, { $set: { order: index + 1 } }, // index从0开始,+1对应自然序号 { new: true } ); }); // 等待所有Promise完成,结果数组顺序与ids完全一致 const sortedAnimals = await Promise.all(promises); console.log(sortedAnimals); return sortedAnimals; }
补充说明
{ new: true }选项:默认findOneAndUpdate返回更新前的文档,若需要获取更新后的结果,必须添加该参数。- 执行方式差异:
for...of是串行执行,适合对顺序要求极高的场景;Promise.all是并行执行,效率更高,但需注意数据库的并发压力。
内容的提问来源于stack exchange,提问作者Ahmed Sbai
相关产品推荐
相关产品推荐

