我需要从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 }))
如何将这三个调用链接起来,以便第三个调用发生在前两个调用之后?
答案 0 :(得分:24)
首先,不确定是否要在componentWillMount
中执行此操作,因为在完成所有这些操作后,您的组件才会呈现,最好将其放在componentDidMount
中,并且有一些默认状态完成这些请求后将更新。其次,你想限制你写的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,
});
}
答案 1 :(得分:11)
你用过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
答案 2 :(得分:5)
聚会晚了一点,但是我喜欢这种将诺言链接起来的模式,将它们返回以使诺言链保持活力。
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));
答案 3 :(得分:4)
我认为你需要这样的东西:
json_encode
答案 4 :(得分:1)
以获得更好的性能和更简洁的代码:
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)
}
}
答案 5 :(得分:0)
这与JS的Promises有关。你可以用不同的方式解决它。对我来说最简单的方法是你应该从第一个到第三个嵌套每个请求。这意味着从第一个请求开始,您应该将第二个axios.get(url)
放入第一个请求的.then()
,并将第三个请求放入第二个请求的.then()
。
对于一般的承诺,您希望.then()
部分承诺内部得到解决,您可以访问response
。因此,通过嵌套,您可以以不那么优雅的方式解决异步问题。
答案 6 :(得分:0)
创建承诺数组,然后使用reduce。
/**
* Runs promises from array of functions that can return promises
* in chained manner
*
* @param {array} arr - promise arr
* @return {Object} promise object
*/
function runPromiseInSequence(arr, input) {
return arr.reduce(
(promiseChain, currentFunction) => promiseChain.then(currentFunction),
Promise.resolve(input)
)
}
// promise function 1
function p1(a) {
return new Promise((resolve, reject) => {
resolve(a * 5)
})
}
// promise function 2
function p2(a) {
return new Promise((resolve, reject) => {
resolve(a * 2)
})
}
// function 3 - will be wrapped in a resolved promise by .then()
function f3(a) {
return a * 3
}
// promise function 4
function p4(a) {
return new Promise((resolve, reject) => {
resolve(a * 4)
})
}
const promiseArr = [p1, p2, f3, p4]
runPromiseInSequence(promiseArr, 10)
.then(console.log) // 1200