Как я могу объединить эти две функции asyn c? - PullRequest
1 голос
/ 29 мая 2020

Я прохожу через массив команд, получая данные команды и игроков для каждой команды ...

У меня есть 2 асинхронные c функции, которые извлекают одни и те же данные, но я не могу понять, как объедините их.

Как это работает в настоящее время, каждый l oop добавляет массив teamPlayers к массиву player в первой функции asyn c. По завершении в моем массиве игроков будет 1450 объектов игроков. Вторая функция asyn c добавляет объект team в массив команд. По завершении у меня есть 32 объекта команды в моем массиве команд.

Я попытался изменить первую функцию asyn c, чтобы получить данные, а затем отправить диспетчеру значение results.teamPlayers, но в итоге я получил массив игроков с 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.lo go и добавьте его каждому игроку в teamPlayers.

Ответы [ 3 ]

3 голосов
/ 29 мая 2020

Так же, как предложение, почему бы вам не создать конечную точку, которая принимает несколько идентификаторов команд, чтобы вам не нужно было отправлять несколько запросов на сервер, она может возвращать все данные сразу в массиве? Кроме того, наличие ключей 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 };
}

Теперь вы можете вызвать функцию и получить ключи teamPlayers или team результата, чтобы получить все, что вам нужно.

0 голосов
/ 29 мая 2020

Я разобрался, но скажите, пожалуйста, если вы думаете, что есть более эффективное решение.

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;
}
0 голосов
/ 29 мая 2020

Чтобы избежать получения одной и той же команды несколько раз, вы можете кэшировать свои результаты. Например, если это резервный магазин, вы можете распределить команды и поместить их в свое состояние redux. Чтобы собрать все это вместе, вы можете написать асинхронную c функцию, которая либо извлекает команды из магазина, либо извлекает, если она еще не была получена.

// 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;
}
...