Axios:链接多个 API 请求

IT技术 reactjs react-native axios
2021-04-09 05:50:21

我需要链接来自 Google Maps API 的一些 API 请求,并且我正在尝试使用 Axios 来完成它。

这是第一个请求,它在 componentWillMount() 中

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

这是第二个请求:

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

然后我们有第三个请求,它依赖于前两个请求的完成:

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 }))

如何链接这三个调用,以便在前两个调用之后发生第三个调用?

6个回答

首先,不确定您是否想在您componentWillMountcomponentDidMount. 其次,你想限制你写的 setStates 的数量,因为它们可能会导致额外的重新渲染,这是一个使用 async/await 的解决方案:

async componentDidMount() {

  // Make first two requests
  const [firstResponse, secondResponse] = 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}`)
  ]);

  // Make third request using responses from the first two
  const thirdResponse = await axios.get('https://maps.googleapis.com/maps/api/directions/json?origin=place_id:' + firstResponse.data.results.place_id + '&destination=place_id:' + secondResponse.data.results.place_id + '&key=' + 'API-KEY-HIDDEN');

  // Update state once with all 3 responses
  this.setState({
    p1Location: firstResponse.data,
    p2Location: secondResponse.data,
    route: thirdResponse.data,
  });

}
完美的。这很棒。
2021-05-25 05:50:21
如何访问 Promise.all() 中的状态?
2021-05-31 05:50:21
@Dravidian,您可以在 promise.all 上封装 try/catch 或链接 .catch。如果您想处理一个失败而其他通过的情况,您也可以交换使用allSettled而不是all. 并且您可能还需要更多关于firstResponse.data.results.place_id在第三个请求中使用之前实际存在的值的逻辑但总体思路是存在的
2021-06-17 05:50:21
在第一个请求中出现错误(仅获取 firstResponse),这种模式如何处理这种情况?
2021-06-19 05:50:21

聚会有点晚了,但我喜欢这种链接Promise的模式,返回它们以保持Promise链的活力。

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));
使用这种技术你如何去捕捉每个单独的错误?类似的问题在这里:github.com/axios/axios/issues/708#issuecomment-317224152
2021-05-27 05:50:21

你用过 axios.all 吗?你可以尝试类似的东西:

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));

这将占用您所有的 get 并将其放入必须使用 .data 调用的响应中,例如: firstResponse.data

那么在这种情况下,我会使用这样的方法:``` axios.get('firstrequest)。then( firstResponse => { axios.get('secondResponse', firstResponse.data.id) } ) ```
2021-05-30 05:50:21
如何传入Auth标题?
2021-06-06 05:50:21
@ZaInKhAn axios.get('request', { headers: { 'X-Octopus-ApiKey': process.env.API_KEY, 'Content-Type': 'application/json' } })
2021-06-07 05:50:21
如果“secondrequest”的输入来自“firstrequest”的响应怎么办?
2021-06-15 05:50:21
请记住,这已被弃用,axios 官方文档建议使用 Promise.all
2021-06-19 05:50:21

为了获得更好的性能和更清晰的代码

1. 使用 promise.all() 或 axios.all() 同时执行 request1 和 request2。所以 request2 将在不等待 request1 响应的情况下执行。request1 和 request2 返回响应后,request3 将根据返回的响应数据作为参数继续执行。
2.模板字符串使用反引号(``)

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)
    }
}
要在 的情况下分别捕获错误axios.all(),请使用
2021-05-22 05:50:21
我如何捕捉来自不同请求的响应?谢谢这个顺便说一句
2021-06-06 05:50:21

我认为你需要这样的东西:

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
       })
如果您注释掉 Promise.all 代码,您会注意到三个 API 调用仍在立即进行。这只能是偶然的,因为 Promise.all 没有生效
2021-05-26 05:50:21