Использование async/await для получения данных из обратного вызова и возврата значения только после разрешения обещания
Я пытаюсь использовать async / await, но я думаю, что я что-то неправильно понял.
в основном, насколько это возможно, я пытаюсь рассчитать расстояние между списком местоположений и одним назначенным местоположением с помощью Google maps api.
вот пример того, что я пытаюсь сделать:https://jsfiddle.net/qu5y69rj/1/
вы можете видеть, что результатом этой функции является undefined
3 раза вместо того что я ожидаю, что будет будь {distance: "ZERO_RESULTS"}
для каждого вызова в случае моего надуманного примера.
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;
}
Почему результат возвращается перед обещание решить? Как я могу вернуть значение result
только после того, как это обещание будет решена? Насколько я понимаю, говоря javascript ждать, я говорю не двигаться вперед, пока это обещание не будет разрешено. Это неправильно? Я в замешательстве, и это заставляет меня выдергивать волосы. Любая помощь приветствуется.
2 ответов
на service.getDistanceMatrix
принимает обратный вызов, что означает, что ti, скорее всего, не возвращает обещание.
однако асинхронные функции ожидают обещаний.
в качестве исправления вы можете обернуть getDistanceMatrix
это в обещании (или используйте другой метод, который возвращает обещание):
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
};
};
существует три способа выполнения асинхронных операций с JavaScript:
-
обратные вызовы: функция принимает обратный вызов в качестве своего окончательного аргумента. Он ничего не возвращает (
undefined
), а если асинхронная операция завершается, вызывается. - обещания: функция возвращает обещание, которое разрешает результат асинхронной операции, когда она завершается.
-
Async / Await: функция возвращает обещайте, и можете использовать
async
ключевое слово, чтобы получить значения асинхронных операций внутри его определения. Все, что возвращается с помощьюreturn
ключевое слово будет завернуто в обещание.
С getDistanceMatrix
принимает обратный вызов, он ничего не возвращает. The await
ключевое слово, используемое в коде, не нужно ждать; он сразу получает undefined
значением, возвращенным getDistanceMatrix
. Когда операция завершается и вызывается обратный вызов,getDistance
давно закончил выполнение и возвращенный.
вам нужно обернуть getDistanceMatrix
таким образом, он возвращает обещание, сделайте getAllDistance()
вернуть обещание, а также, и ждать, что обещание в вашем console.log()
о себе:
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); });