如何结合这两个异步功能?

时间:2020-05-28 23:47:44

标签: javascript axios

我正在遍历一个团队数组,以获取每个团队的团队数据和球员...

我有2个异步函数可以提取相同的数据,但我不知道如何组合它们。

当前,每个循环将teamPlayers数组添加到第一个异步函数中的玩家数组。完成后,我的玩家数组中有1450个玩家对象。第二个异步函数将team对象添加到teams数组。完成后,我的团队数组中将包含32个团队对象。

我尝试更改第一个异步函数以获取数据,然后使分派返回一个results.teamPlayers值,但最终得到一个players数组,其中包含32个数组,每个数组具有x个播放器对象。

async function loadRosters(endPoints, teams, authKey) {
    axios.defaults.headers.common['Authorization'] = authKey;

    const requests = teams.map(teamId => {
        try {
            return axios.get(endPoints.roster + teamId).then(r => r.data.teamPlayers);
        } catch (e) {
            console.log(e);
        }
        return [];
    });

    const results = (await Promise.all(requests)).flat();
    dispatch({ type: 'SET_PLAYERS', value: results });

    return results;
}


async function loadTeamData(endPoints, teams, authKey) {
    axios.defaults.headers.common['Authorization'] = authKey;

    const requests = teams.map(teamId => {
        try {
            return axios.get(endPoints.roster + teamId).then(r => r.data.team);
        } catch (e) {
            //
        }
        return [];
    });

    const results = (await Promise.all(requests)).flat();
    dispatch({ type: 'SET_TEAM_LOGOS', value: results });

    return results;
}

这是我获取的数据结构:

{
  "team": {
    "teamId": "string",
    "abbr": "string",
    "logo": "string"
  },
  "teamPlayers": [
    {
      "firstName": "string",
      "lastName": "string",
      "esbId": "string",
      "position": "string",
      "jerseyNumber": 0,
      "teamAbbr": "string",
      "headshot": "string"
    }
  ]
}

如果我获得了team.logo并将其添加到teamPlayers中的每个玩家,则可能会更简单。

3 个答案:

答案 0 :(得分:3)

仅作为建议,为什么不创建一个接受多个团队ID的终结点,这样就不需要向服务器发送多个请求,它可以一次返回数组中的所有数据?同样,至少从语义上来说,从该端点返回一个team和一个teamPlayers键是有点可疑的设计。无论如何,这是我的最佳尝试:

async function loadTeams(endPoints, teams, authKey) {
    axios.defaults.headers.common['Authorization'] = authKey;

    const requests = teams.map(teamId =>
      axios.get(endPoints.roster + teamId).then(res => res.data, e => {
        console.error(e);
        return { teamPlayers: [], team: [] };
      })
    );

    const allTeamData = await Promise.all(requests);
    // Following variables will aggregate ALL players from ALL teams and
    // ALL logos (? it seems your logos are arrays, but that's a bit weird)
    const allTeamPlayers = [], allTeamLogos = [];

    for (const { teamPlayers, team } of allTeamData) {
      allTeamPlayers.push(...teamPlayers); // spread optional
      allTeamLogos.push(...team); // again, spread optional
    }

    dispatch({ type: 'SET_PLAYERS', value: allTeamPlayers });
    dispatch({ type: 'SET_TEAM_LOGOS', value: allTeamLogos });

    return { teamPlayers: allTeamPlayers, team: allTeamLogos };
}

现在,您可以调用该函数并获取结果的teamPlayersteam键来获取所需的内容。

答案 1 :(得分:0)

为避免多次获取同一团队,您可以缓存结果。例如,如果这是一个Redux商店,则可以派遣团队并将其置于Redux状态。综上所述,您可以编写一个异步功能,该功能可以从商店中检索团队,也可以在尚未获取的情况下获取。

// Not sure how you are getting "dispatch" earlier, but assuming you've got a getState as well...

const inProgress = new Map();

async function loadTeam(endPoints, teamId, authKey) {
  const { teams } = getState();
  if (teamId in teams) {
    return teams[teamId];
  }

  let promise = inProgress.get(teamId);
  if (!promise) {
    axios.defaults.headers.common['Authorization'] = authKey;
    promise = axios.get(endPoints.roster + teamId);
    inProgress.set(teamId, promise);
  }

  const { data: team } = await promise;
  inProgress.delete(teamId);

  // TODO: add a reducer that puts this team in your state
  dispatch({ type: 'SET_TEAM', payload: { teamId, team } });
  return team;
}

现在,如果您使用此loadTeam函数,则不必担心重复获取:

async function loadRosters(endPoints, teams, authKey) {
    axios.defaults.headers.common['Authorization'] = authKey;

    const requests = teams.map(teamId => loadTeam(endPoints, teamId, authKey));

    const results = (await Promise.all(requests))
      .map(team => team.teamPlayers)
      .flat();
    dispatch({ type: 'SET_PLAYERS', value: results });

    return results;
}

答案 2 :(得分:0)

我知道了,但是请告诉我您是否认为有一种更有效的解决方案。

async function loadRosters(endPoints, teams, authKey) {
    axios.defaults.headers.common['Authorization'] = authKey;

    const requests = teams.map(teamId => {
        try {
            return axios.get(endPoints.roster + teamId).then(r => r.data);
        } catch (e) {
            //
        }
        return [];
    });

    const results = (await Promise.all(requests)).flat();
    dispatch({ type: 'SET_PLAYERS', value: results.map(r => r.teamPlayers).flat(Infinity) });
    dispatch({ type: 'SET_TEAM_LOGOS', value: results.map(r => r.team) });

    return results;
}