如何用数组中每个matchId调用异步函数并存储结果?解决相关报错
问题描述
我有一个返回matchIds数组的函数,还有一个根据matchId返回对应比赛数据的异步函数getMatchData:
async function getMatchData(matchId){ const response = await fetch(`https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}?api_key=`+key); var data = await response.json(); let matchData= { teams: data.info.teams.map(element => team = { teamid: element.teamId, win: element.win }), players: data.info.participants.map(element => obj = { team: element.teamId, champ: element.championName, champIcon: element.championName + '_0.jpg', summoner: element.summonerName, level: element.champLevel, build: { item1: element.item1, item2: element.item2, item3: element.item3, item4: element.item4, item5: element.item5, item6: element.item6, item0: element.item0 }, kills: element.kills, deaths: element.deaths, assists: element.assists, kda: (element.kills + element.assists) / element.deaths, cs: element.totalMinionsKilled + element.neutralMinionsKilled, victory: element.win }) } return matchData }
我想把matchIds数组(即matches数组)里的每个matchId传入getMatchData,并把结果存到数组或对象里,于是用map遍历调用:
let matchHistoryData= matches.map(element=>getMatchData(element)) console.log(matchHistoryData);
但结果返回[Promise {}, Promise {}, ...]形式的数组,还出现报错:Cannot read properties of undefined (reading 'teams'),求解决办法。
解决方案
1. 解决Promise数组问题
getMatchData是异步函数,调用后会直接返回Promise对象,所以map遍历得到的是Promise数组。要拿到实际的比赛数据,需要用Promise.all等待所有Promise完成,同时要将这段逻辑放在async函数中执行:
async function fetchAllMatchData() { // 用Promise.all等待所有请求完成 const matchHistoryData = await Promise.all(matches.map(matchId => getMatchData(matchId))); console.log(matchHistoryData); // 这里会得到包含所有比赛数据的数组 } // 调用这个异步函数 fetchAllMatchData();
Promise.all会等待传入的所有Promise都成功resolve后,返回一个包含所有结果的数组,这样就能拿到你需要的实际数据。
2. 解决"Cannot read properties of undefined (reading 'teams')"报错
这个报错说明data.info或者data.info.teams是undefined,大概率是请求返回的内容不符合预期(比如API key无效、matchId错误、请求限流,或者API返回结构变化),可以通过以下方式修复:
(1)添加请求状态和数据格式校验
在getMatchData里先检查请求是否成功,再校验返回的数据结构:
async function getMatchData(matchId){ const response = await fetch(`https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}?api_key=`+key); // 检查请求是否成功(状态码200-299) if (!response.ok) { throw new Error(`请求失败: ${response.status} ${response.statusText}`); } const data = await response.json(); // 检查data.info是否存在 if (!data?.info) { throw new Error(`比赛数据格式异常,缺少info字段: ${JSON.stringify(data)}`); } let matchData= { // 用可选链+默认空数组,避免teams不存在时报错 teams: data.info.teams?.map(element => ({ teamid: element.teamId, win: element.win })) || [], // 同理处理participants,同时修复KDA除以0的问题 players: data.info.participants?.map(element => ({ team: element.teamId, champ: element.championName, champIcon: element.championName + '_0.jpg', summoner: element.summonerName, level: element.champLevel, build: { item1: element.item1, item2: element.item2, item3: element.item3, item4: element.item4, item5: element.item5, item6: element.item6, item0: element.item0 }, kills: element.kills, deaths: element.deaths, assists: element.assists, // 当deaths为0时,KDA直接取击杀+助攻数,避免除以0报错 kda: element.deaths === 0 ? (element.kills + element.assists) : (element.kills + element.assists) / element.deaths, cs: (element.totalMinionsKilled || 0) + (element.neutralMinionsKilled || 0), victory: element.win })) || [] } return matchData }
(2)关键修复点说明
- 请求状态检查:确保请求成功才继续处理数据,避免解析错误的响应体导致异常。
- 可选链操作符
?.:访问嵌套属性时如果上层属性不存在,会直接返回undefined,不会抛出报错,配合|| []给默认空数组,保证代码能继续执行。 - KDA除以0修复:当玩家死亡数为0时,直接返回击杀+助攻数,避免出现NaN或报错。
内容的提问来源于stack exchange,提问作者ThePridestalker
相关产品推荐
相关产品推荐

