遍历对象数组时为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
相关产品推荐
相关产品推荐

