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

如何用Promise实现map异步执行?我的React代码输出不符合预期

异步map结合Promise.all的问题修复

问题场景

想通过map实现异步批量操作,用了async和Promise.all,但输出顺序和结果都不符合预期。代码、预期输出和实际输出如下:

原代码

// idList是[1,2,3],每个id对应的接口返回total为[2,3,2]
useEffect(()=> {
  countNumFunc(idList)
})

const countNumFunc = (idlist) => {
  let count = 0
  Promise.all(idList.map(async (id) => {
    console.log("id = ", id)
    getInfoFromDb(id).then((res) => {
      if(res.data) {
        count = count + res.data.total
        console.log("Count = ", res.data.total)
      }
    }).catch(error => {
        console.log("error = ", error)
    })
  }))
  console.log("Count total = ", count)
} 

预期输出

id = 1
Count = 2
id = 2
Count = 5
id = 3
Count = 7
Count total = 7

实际输出

id = 1
id = 2
id = 3
Count total = 0
Count = 2
Count = 3
Count = 2

问题原因

  1. 异步执行顺序错误:Promise.all里的map函数虽然加了async,但内部用.then处理异步时没有返回这个Promise,导致Promise.all根本没等getInfoFromDb执行完成就继续走同步代码,所以console.log("Count total = ", count)会先执行,此时count还是初始值0。
  2. 累加方式不可靠:直接在异步回调里修改外部的count变量,多个异步操作同时修改会导致竞态,而且无法保证顺序。

修复方案

useEffect(()=> {
  countNumFunc(idList)
}, [idList]) // 加上依赖项,避免无意义重复执行

const countNumFunc = async (idList) => {
  try {
    // 让每个异步操作返回对应的total,Promise.all收集所有结果
    const totals = await Promise.all(idList.map(async (id) => {
      console.log("id = ", id)
      const res = await getInfoFromDb(id)
      const currentTotal = res.data?.total || 0
      console.log("当前累加值 = ", currentTotal)
      return currentTotal
    }))
    // 所有异步完成后统一累加
    const totalCount = totals.reduce((sum, num) => sum + num, 0)
    console.log("Count total = ", totalCount)
    return totalCount
  } catch (error) {
    console.log("error = ", error)
  }
} 

修复说明

  • 把countNumFunc改为async函数,用await等待Promise.all完成,确保后续代码在所有异步操作结束后执行。
  • 用await替代.then处理getInfoFromDb的异步结果,同时返回每个id对应的total值,让Promise.all收集成数组。
  • 用reduce统一累加数组中的值,避免异步修改外部变量的竞态问题。
  • 给useEffect加上idList依赖项,符合React性能优化的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:55:21