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.
async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.
Async functions The word “async” before a function means one simple thing: a function always returns a promise. Other values are wrapped in a resolved promise automatically. So, async ensures that the function returns a promise, and wraps non-promises in it.
The await keyword is used in an async function to ensure that all promises returned in the async function are synchronized, ie. they wait for each other. Await eliminates the use of callbacks in .
The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result.
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); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With