Mongoose查询时reduce返回空数组但内部打印有值如何修复
问题原因
- 你在
forEach中传入了async异步函数,forEach不会等待异步任务执行完成就会直接结束遍历,外层的reduce是同步方法,执行完毕返回空数组时,内部的populate异步查询还没跑完。等异步查询完成往results里推值的时候,data已经被赋值为空数组了,所以才会出现先打印空数组、后打印有值数组的情况。 reduce本身不支持等待内部异步任务执行,不能直接在reduce的遍历回调里处理异步逻辑。
修复后的代码
// Fetch users from db let activeUsers = await User.find().populate({ path: 'campaigns', match: { active: true }, }) const data = [] // 用for of遍历支持await等待异步操作完成 for (const user of activeUsers) { for (const campaign of user.campaigns) { const { landings } = await campaign.populate({ path: 'landings', match: { active: true }, }) // 过滤符合要求的landing id const landingsIds = landings.reduce((results, landing) => { const matchLanding = landingsFromBinom.find(binomLanding => parseInt(binomLanding.id) === landing.id && binomLanding.inject >= landing.todayVisitors ) if (matchLanding) results.push(landing.id) return results }, []) // 仅存在符合条件的landing时推入数据,不需要可删除该判断 if (landingsIds.length) { data.push({ landings: landingsIds, user: user._id }) } } } console.log(data)
可选优化(并发请求提升效率)
如果活跃用户和campaign数量较多,逐个await会拖慢处理速度,可以用Promise.all批量处理异步请求:
let activeUsers = await User.find().populate({ path: 'campaigns', match: { active: true }, }) const data = [] const campaignTasks = [] // 先收集所有populate异步任务 for (const user of activeUsers) { for (const campaign of user.campaigns) { campaignTasks.push((async () => { const { landings } = await campaign.populate({ path: 'landings', match: { active: true }, }) const landingsIds = landings.reduce((results, landing) => { const matchLanding = landingsFromBinom.find(binomLanding => parseInt(binomLanding.id) === landing.id && binomLanding.inject >= landing.todayVisitors ) if (matchLanding) results.push(landing.id) return results }, []) if (landingsIds.length) { data.push({ landings: landingsIds, user: user._id }) } })()) } } // 等待所有异步任务执行完成 await Promise.all(campaignTasks) console.log(data)
内容的提问来源于stack exchange,提问作者sky sky
相关产品推荐
相关产品推荐

