I'm trying to use async/await but I think I'm misunderstanding something critically.
As basically as possible, I am trying to calculate the distance between a list of locations and one designated location using google maps api.
Here is a rough example of what I'm trying to do: https://jsfiddle.net/qu5y69rj/1/
You can see that the result of that function is undefined
3 times instead of what I would expect which would be {distance: "ZERO_RESULTS"}
for each call in the case of my contrived example.
getDistance = async (start, end) => {
const origin = new google.maps.LatLng(start[0], start[1]);
const final = new google.maps.LatLng(end[0], end[1]);
const service = new google.maps.DistanceMatrixService();
let result; //need to return this value!
await service.getDistanceMatrix(
{
origins: [origin],
destinations: [final],
travelMode: 'DRIVING'
}, (response, status) => {
if(status === 'OK') result = {distance: response.rows[0].elements[0].status}
}
)
return result;
}
Why is result being returned before the promise is resolved? How can I return the value of result
only after that promise is resolved? It is my understanding that by telling javascript to await, I'm saying don't move forward until this promise has resolved. Is that incorrect? I'm pretty confused and this has me pulling my hair out. Any help is appreciated.
The service.getDistanceMatrix
accepts a callback which means ti most likely doesn't return a promise.
However, async functions expect promises.
As a fix, you can wrap getDistanceMatrix
it in a promise (or use another method that does return a promise):
const getDistanceMatrix = (service, data) => new Promise((resolve, reject) => {
service.getDistanceMatrix(data, (response, status) => {
if(status === 'OK') {
resolve(response)
} else {
reject(response);
}
})
});
getDistance = async (start, end) => {
const origin = new google.maps.LatLng(start[0], start[1]);
const final = new google.maps.LatLng(end[0], end[1]);
const service = new google.maps.DistanceMatrixService();
const result = await getDistanceMatrix(
service,
{
origins: [origin],
destinations: [final],
travelMode: 'DRIVING'
}
)
return {
distance: result.rows[0].elements[0].status
};
};
There are three ways to do async operations with JavaScript:
undefined
), and when the async operation completes, the callback is called. async
keyword to get the values of async operations inside its definition. Whatever is returned using the return
keyword will be wrapped in a promise. Since getDistanceMatrix
accepts a callback, it returns nothing. The await
keyword as used in the code doesn't need to wait; it immediately gets the undefined
value returned by getDistanceMatrix
. When the operation completes and the callback is called, the getDistance
has long finished executing and returned.
You need to wrap getDistanceMatrix
so it returns a promise, make getAllDistance()
return a promise as well, and await that promise in your console.log()
statement:
const coords = [
['-36.22967', '-125.80271'],
['54.06395', '54.06395'],
['-5.00263', '-137.92806']
];
function getDistance (start, end) {
const origin = new google.maps.LatLng(start[0], start[1]);
const final = new google.maps.LatLng(end[0], end[1]);
const service = new google.maps.DistanceMatrixService();
return new Promise((resolve, reject) => {
service.getDistanceMatrix(
{
origins: [origin],
destinations: [final],
travelMode: 'DRIVING'
}, (response, status) => {
if(status === 'OK') {
resolve({ distance: response.rows[0].elements[0].status });
} else {
reject(new Error('Not OK'));
}
}
);
});
}
function getAllDistance (starts, end) {
const promisedDistances = starts.map((start) => getDistance(start, end));
// Promise.all turns an array of promises into a promise
// that resolves to an array.
return Promise.all(promisedDistances);
}
getAllDistance(coords, ['-30.23978', '-161.31203'])
.then(result => { console.log(result); });
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.