使用async / await从回调中获取数据,并仅在解析promise后返回值

问题描述 投票:6回答:2

我正在尝试使用async / await,但我认为我批判性地误解了一些东西。

尽可能基本上,我试图使用谷歌地图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等待,我说在这个承诺解决之前不要继续前进。这是不正确的?我很困惑,这让我把头发拉了出来。任何帮助表示赞赏。

javascript asynchronous async-await
2个回答
6
投票

service.getDistanceMatrix接受回调,这意味着很可能不会返回承诺。

但是,异步函数需要承诺。

作为修复,您可以将getDistanceMatrix包装在promise中(或使用另一个返回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
  };
};

3
投票

使用JavaScript进行异步操作有三种方法:

  1. 回调:函数接受回调作为其最终参数。它什么都不返回(undefined),当异步操作完成时,调用回调。
  2. Promises:函数返回一个promise,它在完成时解析为异步操作的结果。
  3. Async / Await:函数返回一个promise,可以使用async关键字在其定义中获取异步操作的值。使用return关键字返回的任何内容都将包含在promise中。

由于getDistanceMatrix接受回调,它什么都不返回。代码中使用的await关键字不需要等待;它会立即获得undefined返回的getDistanceMatrix值。当操作完成并调用回调时,getDistance已经完成执行并返回。

你需要包装getDistanceMatrix以便它返回一个promise,让getAllDistance()返回一个promise,并等待你的console.log()语句中的这个promise:

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); });
© www.soinside.com 2019 - 2024. All rights reserved.