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

JavaScript中forEach内赋值的dataShops变量外部访问为空是什么原因?

问题原因分析

你遇到的是前端异步编程的典型执行顺序问题,核心原因如下:

  • Array.prototype.forEach 本身没有等待异步回调执行完成的机制,你传入的async回调会被forEach依次触发后,就直接继续执行后续代码,不会等待回调内部的await异步逻辑执行结束。
  • 你写的MongoDB查询是异步IO操作,在forEach遍历结束后直接执行外部的console.log(dataShops)和setDataMain时,所有查询请求还未返回结果,dataShops还停留在初始的空数组状态,所以只能拿到空值。
  • 循环内部的打印是在异步查询await拿到结果之后才执行的,此时已经完成了dataShops的拼接操作,所以能看到完整内容,这两处打印的实际执行顺序和你代码书写的顺序是相反的。
修复方案

把forEach替换为map收集所有异步请求的Promise实例,再用Promise.all等待所有异步请求执行完成后再处理结果即可,修改后参考代码如下:

// 函数本身需要加async修饰
const fetchSales = async () => {
  const dateInitial = moment(dayInitial, 'ddd, D MMM YYYY').format('YYYY-MM-DD')
  const dateFinal = moment(dayFinal, 'ddd, D MMM YYYY').format('YYYY-MM-DD')
  try {
    setIsLoading(true)
    // 收集所有异步查询的Promise
    const requestPromises = app.currentUser.customData.lojas.map(async (value) => {
      const mongo = app.currentUser.mongoClient("mongodb-atlas").db(value.base)
      return mongo.collection("vendas").find({
        data: {
          $gte: dateInitial,
          $lte: dateFinal
        }
      }, { sort: { data: 1, hora: 1 } })
    })
    // 等待所有查询返回结果
    const allData = await Promise.all(requestPromises)
    // 扁平化数组合并所有门店的查询结果
    const dataShops = allData.flat()
    if (mounted) {
      console.log(dataShops)
      setDataMain(dataShops)
    }
  } catch (e) {
    setError(e)
  } finally {
    setRefreshing(false)
    setIsLoading(false)
  }
}

内容的提问来源于stack exchange,提问作者Bruno

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 11:27:00