You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 01:45:04