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

遍历对象数组时为Axios响应赋值的实现难题

解决Axios异步请求中数组赋值问题

你的核心问题是异步请求的执行时机——matchedUsers.forEach里的Axios请求是异步操作,当你执行console.log(timedUsers)和res.json(timedUsers)时,这些请求还没完成,所以数组始终是空的。

下面是两种可行的解决方案:


方案1:使用Promise.all + map(基于原有Promise链式调用)

app.get('/matchedusers', (req, res) => {
  plexClient.getAllUsers().then(plexUsers => {
    axios.get('https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_users_table&length=150')
      .then((tautulliUser) => {
        const tautulliUsers = tautulliUser.data.response.data.data
        const matchedUsers = []
        
        // 匹配用户逻辑保持不变
        tautulliUsers.forEach((tautulliUser) => {
          plexUsers.forEach((plexUser) => {
            if(tautulliUser.username == plexUser.username || tautulliUser.username == plexUser.email){
              matchedUsers.push({id: plexUser.id, username: plexUser.username, email: plexUser.email})
            }
          })
        })

        // 1. 用map替代forEach,收集所有请求的Promise
        const userWatchTimePromises = matchedUsers.map((user) => {
          // 注意:修正参数为user.id(你的matchedUsers里存的是id字段,不是user_id)
          return axios.get(`https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_user_watch_time_stats&user_id=${user.id}&query_days=7`)
            .then((watchTime) => {
              // 2. 提前合并用户数据与响应结果
              return {...user, watchTime: watchTime.data}
            })
        })

        // 3. 等待所有请求完成,直接拿到最终数组
        Promise.all(userWatchTimePromises)
          .then((timedUsers) => {
            console.log(timedUsers)
            res.json(timedUsers)
          })
          .catch((err) => {
            console.error('获取观看时间失败:', err)
            res.status(500).json({error: '获取用户数据失败'})
          })
      })
      .catch((err) => {
        console.error('获取Tautulli用户列表失败:', err)
        res.status(500).json({error: '获取用户列表失败'})
      })
  })
  .catch((err) => {
    console.error('获取Plex用户失败:', err)
    res.status(500).json({error: '获取Plex用户失败'})
  })
})

关键改动说明:

  • 用map替代forEach:map会返回包含所有请求Promise的数组,方便后续用Promise.all统一等待
  • 修正请求参数:你的matchedUsers中存储的是id字段(来自plexUser.id),所以请求时要用user.id而非user.user_id
  • 提前合并数据:在单个请求的then中完成用户信息与响应的合并,避免后续额外处理
  • 新增错误捕获:所有异步操作添加catch分支,避免请求失败时服务器无响应

方案2:使用async/await(代码更简洁直观)

app.get('/matchedusers', async (req, res) => {
  try {
    // 同步写法获取初始数据
    const plexUsers = await plexClient.getAllUsers()
    const tautulliResponse = await axios.get('https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_users_table&length=150')
    const tautulliUsers = tautulliResponse.data.response.data.data
    const matchedUsers = []

    // 匹配用户逻辑不变
    tautulliUsers.forEach((tautulliUser) => {
      plexUsers.forEach((plexUser) => {
        if(tautulliUser.username == plexUser.username || tautulliUser.username == plexUser.email){
          matchedUsers.push({id: plexUser.id, username: plexUser.username, email: plexUser.email})
        }
      })
    })

    // 并行请求并合并结果
    const timedUsers = await Promise.all(matchedUsers.map(async (user) => {
      const watchTime = await axios.get(`https://tautulli.link/api/v2?apikey=API-KEY&cmd=get_user_watch_time_stats&user_id=${user.id}&query_days=7`)
      return {...user, watchTime: watchTime.data}
    }))

    console.log(timedUsers)
    res.json(timedUsers)
  } catch (err) {
    console.error('请求出错:', err)
    res.status(500).json({error: '获取用户数据失败'})
  }
})

这个版本用async/await把异步代码转换成同步写法,逻辑更清晰,同时用try/catch统一处理所有错误,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:01:12