web-dev-qa-db-fra.com

Axios: chaîner plusieurs requêtes d'API

Je dois chaîner quelques requêtes d'API de l'API Google Maps et j'essaie de le faire avec Axios.

Voici la première requête, qui se trouve dans composantWillMount ()

axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p1)
  .then(response => this.setState({ p1Location: response.data }))  }

Voici la deuxième demande:

axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p2)
  .then(response => this.setState({ p2Location: response.data }))

Ensuite, nous avons une troisième demande, qui dépend de l’achèvement des deux premières:

axios.get('https://maps.googleapis.com/maps/api/directions/json?origin=place_id:' + this.state.p1Location.results.place_id + '&destination=place_id:' + this.state.p2Location.results.place_id + '&key=' + 'API-KEY-HIDDEN')
  .then(response => this.setState({ route: response.data }))

Comment puis-je enchaîner ces trois appels pour que le troisième survienne après les deux premiers?

9
Freddy

Tout d’abord, vous n'êtes pas sûr de vouloir le faire dans votre componentWillMount, car votre composant ne sera pas rendu tant que tout n’aura pas été fait, il est préférable de le placer dans componentDidMount et d’avoir certains états par défaut à mettre à jour une fois ces requêtes effectuées. Deuxièmement, vous voulez limiter le nombre de setStates que vous écrivez, car ils pourraient entraîner de nouveaux rendus, voici une solution utilisant async/wait:

async componentDidMount() {
  const firstRequest = await axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p1);
  const secondRequest = await axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p2);
  const thirdRequest = await axios.get('https://maps.googleapis.com/maps/api/directions/json?origin=place_id:' + firstRequest.data.results.place_id + '&destination=place_id:' + secondRequest.data.results.place_id + '&key=' + 'API-KEY-HIDDEN');

  this.setState({
    p1Location: firstRequest.data,
    p2Location: SecondRequest.data,
    route: thirdRequest.data,
  });
}
17
Matt Aft

Avez-vous utilisé axios.all? Vous pouvez essayer avec quelque chose de similaire:

axios.all([axios.get(`firstrequest`),
           axios.get(`secondrequest`),
           axios.get(`thirdrequest`)])
     .then(axios.spread((firstResponse, secondResponse, thirdResponse) => {  
         console.log(firstResponse.data,secondResponse.data, thirdResponse.data);
     }))
     .catch(error => console.log(error));

Cela prendra tout votre argent et le mettra dans une réponse qui doit être appelée avec .data comme: firstResponse.data

8
Ricardo Gonzalez

Un peu tard pour la fête, mais j'aime bien ce schéma consistant à enchaîner les promesses et à les renvoyer pour maintenir la chaîne de promesses en vie.

axios
  .get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p1')
  .then(response => {
    this.setState({ p1Location: response.data });
    return axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p2');
  })
  .then(response => {
    this.setState({ p2Location: response.data });
    return axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p3');
  })
  .then(response => {
    this.setState({ p3Location: response.data });
  }).catch(error => console.log(error.response));
4
chrisz

Je pense que vous avez besoin de quelque chose comme ça: 

const firstRequest = axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p1)
      .then(response => this.setState({ p1Location: response.data }))  }

const secondRequest = axios.get('https://maps.googleapis.com/maps/api/geocode/json?&address=' + this.props.p2)
  .then(response => this.setState({ p2Location: response.data }))

const thirdRequest = axios.get('https://maps.googleapis.com/maps/api/directions/json?origin=place_id:' + this.state.p1Location.results.place_id + '&destination=place_id:' + this.state.p2Location.results.place_id + '&key=' + 'API-KEY-HIDDEN')
  .then(response => this.setState({ route: response.data }))


Promise.all([firstRequest, secondRequest])
       .then(() => {
           return thirdRequest
       })
4
Morleee

Pour de meilleures performances et un code plus propre :

1. Utilisez promise.all () ou axios.all () pour exécuter request1 et request2 simultanément. Donc, request2 sera exécuté sans attendre la réponse à request1. Une fois que request1 et request2 ont renvoyé la réponse, request3 continuera son exécution en fonction des données de réponse renvoyées en tant que paramètre.
2. Les chaînes de modèles utilisent des ticks arrière (``)

async componentDidMount(){
    try{
        const [request1, request2] = await Promise.all([
           axios.get(`https://maps.googleapis.com/maps/api/geocode/json?&address=${this.props.p1}`),
           axios.get(`https://maps.googleapis.com/maps/api/geocode/json?&address=${this.props.p2}`)
        ]);

        const request3 = await axios.get(`https://maps.googleapis.com/maps/api/directions/json?origin=place_id:${request1.data.results.place_id}&destination=place_id:${request2.data.results.place_id}&key=${API-KEY-HIDDEN}`);
        console.log(request3);
    }
    catch(err){
        console.log(err)
    }
}
0
Toh Ban Soon

Ceci est lié à Promises de JS. Vous pouvez le résoudre de différentes manières. Pour moi, le moyen le plus simple consiste à imbriquer chaque demande, de la première à la troisième. Cela signifie qu'à partir de la première demande, vous devez placer votre deuxième axios.get(url) dans le .then() de la première demande et placer la troisième demande dans le .then() de la deuxième demande. 

Pour les promesses en général, vous vous attendez à ce que la partie promesse de .then() soit résolue et que vous puissiez avoir accès à response. Ainsi, en imbriquant, vous pouvez résoudre le problème d’être asynchrone d’une manière moins élégante.

0
milkersarac