繁体   English   中英

使用async / await从回调中获取数据并仅在解决承诺后返回值

[英]Using async/await to get data from a callback and return a value only after a promise is resolved

我正在尝试使用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等待,我是说直到这个诺言得以解决之前,不要前进。 那不对吗? 我很困惑,这让我拔头发。 任何帮助表示赞赏。

service.getDistanceMatrix接受回调,这意味着ti最有可能不返回承诺。

但是,异步功能会带来希望。

作为解决方法,您可以将getDistanceMatrix包裹在一个getDistanceMatrix中(或使用另一个返回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进行异步操作的方法有以下三种:

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

由于getDistanceMatrix接受回调,因此不返回任何内容。 代码中使用的await关键字不需要等待; 它立即获得getDistanceMatrix返回的undefined值。 当操作完成并调用回调时, 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); });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM