Как сделать асинхронные вызовы внутри forEach (), который зависит от данных другого асинхронного вызова? - PullRequest
0 голосов
/ 29 декабря 2018

Я работаю с API и хочу сделать несколько звонков из моего приложения React.Это асинхронные вызовы, вложенные в forEach ().Я получаю все обещания и помещаю их в массив обещаний.Затем используйте метод axios.all (), как описано в axios docs, но когда я помещаю результаты этих обещаний в массив myData, я получаю пустой массив.

Кроме метода axios.all (обещания), который я пробовал вкладыватьthen () вызывает Promises, но это все усложняет.Вот мой код:

componentDidUpdate(nextProps, nextState) {
    if (this.props.to !== nextProps.to || this.props.from !== 
nextProps.from) {
  let promises = [];
  Axios.get(
    `http://localhost:3000/api/visits?from=${this.props.from}&to=${
      this.props.to
    }`
  ).then(res => {
    res.data.forEach(visit => {
      promises.push(
        Axios.get(`http://localhost:3000/api/clients/${visit.clientId}`
        })
      );
    });
    Axios.all(promises).then(results => {
      results.forEach(res => {
        const clientProps = {
          name: res.data[0].name,
          lastname: res.data[0].lastname,
          mobile_number: res.data[0].mobile_number
        };
        myData.push(clientProps); // Here I am pushing the data to a global array
      });
this.setState({myData})
    });
  });
 }
}

Когда я запускаю код, я ожидаю, что массив "myData" будет заполнен данными, извлеченными из вызова API, но вместо этого я получу пустой массив.Есть ли способ обойти эту проблему?

// I try to access data from this.state inside the render() method of my class component to generate a Table data with the name property.

 <td>{this.state.myData[index].name}</td>

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018
getVisits(from, to) {
  return Axios.get(`http://localhost:3000/api/visits?from=${from}&to=${to}`);
}

getClients(ids) {
  return Axios.all(ids.map(id => Axios.get(`http://localhost:3000/api/clients/${id}`));
}

async getClientsOfVisits(from, to) {
  const response = await this.getVisits(from, to);
  const promises = await this.getClients(response.data.map(visit => visit.clientId)));

  return promises.map(res => res.data[0]);
}

componentDidUpdate(nextProps, nextState) {
  const { to, from } = this.props;
  const toChanged = to !== nextProps.to;
  const fromChanged = from !== nextProps.from;

  if (toChanged || fromChanged) {
    this.getClientsOfVisits(to, from).then(myData => {
      this.setState({ myData });
    })
  }
}
0 голосов
/ 30 декабря 2018

Я думаю, эта версия более удобна.

componentDidUpdate(nextProps, nextState) {
    if (this.props.to !== nextProps.to || this.props.from !== 
nextProps.from) {
  let promises = [];
  Axios.get(
    `http://localhost:3000/api/visits?from=${this.props.from}&to=${
      this.props.to
    }`
  ).then(res => {
    return Axios.all(res.data.map(visit => {
      return Axios.get(`http://localhost:3000/api/clients/${visit.clientId}`)
    }))
  })
  .then(results => {
      return results.map(res => {
          return {
          name: res.data[0].name,
          lastname: res.data[0].lastname,
          mobile_number: res.data[0].mobile_number
        };
      });
    })
  .then(clientProps => {
    // then update state or dispatch an action
    this.setState(() => ({myData: clientProps}));
  });

}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...