Реагировать на useEffect и Axios: выполнение связанных вызовов API внутри 'then'

Я работаю с NHL API и получаю хоккейную статистику для своего приложения. У API есть несколько конечных точек, которые я использую для доступа к статистике игроков.

Roster endpoint

https://statsapi.web.nhl.com/api/v1/teams/3/roster

После получения этих данных я могу получить доступ к объекту с именем person, который содержит идентификационный номер для конечной точки API отдельного игрока, который содержит информацию о родословной (т.е. страну, из которой они происходят, рост / вес и т. Д.). Затем я могу отправить запрос API, который выглядит так, чтобы получить больше данных для этого отдельного игрока, в данном случае 8476191 - это идентификационный номер.

Pedigree Info endpoint:

https://statsapi.web.nhl.com/api/v1/people/8476191

Я также могу передать идентификационный номер 8476191 в конечную точку статистики, которая содержит статистику для того же игрока.

Stats endpoint:

https://statsapi.web.nhl.com/api/v1/people/8476191/stats?stats=statsSingleSeason&season=20182019

Я бы хотел отправить запрос Roster endpoint, получить идентификационные номера для каждого игрока в списке, а затем выполнить последующие вызовы API для Pedigree info endpoint и stats endpoint, используя идентификационный номер.

Как я могу сделать Axios запрос на получение к конечной точке реестра, а затем вложить еще два запроса на получение в вызов, который может получить доступ к идентификационному номеру из первого вызова? Вот что я пытался:

// State for retrieving player ID numbers from roster endpoint
const [playerIDNumbers, setPlayerIDNumbers] = useState([]);

useEffect(() => {
    // Get the roster data, set playerIdNumbers to an array containing all the ID numbers
   axios.get(`https://statsapi.web.nhl.com/api/v1/teams/${teams[teamName].id}/roster`)
       .then(res => {
           setPlayerIDNumbers(Object.values(res.data.roster).map((x) => {
               return x.person.id;
           }));
           // res now contains all the ID numbers
           console.log(res);
       })
       // After grabbing all the ID numbers for each player on the roster, I want to map through each ID 
       // in the array and send a request for each player's pedigree data
       .then(res => {
           // Later in my code I created an array to contain the IDs called playerIDArr
           playerIDArr.map((playerID) => {
               axios.get(`https://statsapi.web.nhl.com/api/v1/people/${playerID}/`)
           })
           console.log('Player ID call returned : ' + res);
       })
       // After this is done I want to make a third request using the ID numbers to grab the stats /////from the stats endpoint
       /* Stats Axios request would go here */
       .catch(err => {
           console.log('Error : ' + err);
       })
}, [])

person Nick Kinlen    schedule 09.05.2020    source источник
comment
Не уверен, почему вы устанавливаете номера идентификаторов игроков в состоянии, вы можете вернуть числа и выполнить Promise.all с идентификаторами в следующем .then. В настоящее время вы пытаетесь использовать устаревшее закрытие playerIDArr   -  person HMR    schedule 09.05.2020


Ответы (1)


Нет необходимости сохранять состояние, вот как это сделать с помощью замыкания:

useEffect(() => {
  axios.get(`https://statsapi.web.nhl.com/api/v1/teams/${teams[teamName].id}/roster`)
    // get all ids
    .then(res => Object.values(res.data.roster).map((x) => x.person.id))
    // map through ids and retrieve the data 
    .then(ids => {
      const people = Promise.all(ids.map(id => axios.get(`https://statsapi.web.nhl.com/api/v1/people/${id}/`)))

      const stats = Promise.all(ids.map(id => axios.get(`https://statsapi.web.nhl.com/api/v1/stats/${id}/`)))

      return Promise.all([people, stats])

    }).catch(err => {
      console.log('Error : ' + err);
    })
})

// or using async/await, and some refactoring

const getRoster = id => axios.get(`https://statsapi.web.nhl.com/api/v1/teams/${id}/roster`)

const getPerson = id => axios.get(`https://statsapi.web.nhl.com/api/v1/people/${id}/`)

const getStats = id => axios.get(`https://statsapi.web.nhl.com/api/v1/stats/${id}/`)

useEffect(() => {
  const res = await getRoster(teams[teamName].id)
  const ids = Object.values(res.data.roster).map(x => x.person.id)
  return Promise.all(ids.map(id => Promise.all([getPerson(id), getStats(id)])))
})

person thedude    schedule 09.05.2020
comment
Обе версии будут работать, но результаты будут упакованы по-разному. Чтобы быть эквивалентной первой версии, вторая должна быть return Promise.all([ Promise.all(ids.map(getPerson)), Promise.all(ids.map(getStats)) ]) (по крайней мере, я так думаю). - person Roamer-1888; 10.05.2020