在恢复功能执行之前,如何等待promise解决

问题描述

我有一个使用地理编码API将字符串(地址/邮政编码/城市)转换为坐标的函数。我还有另一个功能,需要从地理编码api返回的坐标来调用一个搜索事件的api。但是,我是异步javascript的新手,我在使用异步/等待时遇到了麻烦。事件api表示应从地址解析api返回的坐标未定义,但是几秒钟后,坐标被返回。我需要事件api才能停止执行,直到从地址解析api返回坐标为止。有人可以指出我正确的方向吗?

这是这两个函数代码

function toLatLng(input) {
  $.ajax({
    type: "get",url: GEOCODE_API_URL + input,datatype: "json",success: (data) => {
      if(data.status === "OK") {
        return new Promise((resolve,reject) => {
          resolve(data.results[0].geometry.location);
        });
      }
      else if(data.status === "ZERO_RESULTS") {
        alert("The search yielded no results");
      }
      else {
        alert("Unable to search for events");
      }
    },error: (error) => {
      console.log(error);
    },});

async function getEvents(input) {
   let coordinates = await toLatLng(input);
   let queryStr = `&latlong=${coordinates.lat},${coordinates.lng}`
   $.ajax({
     type: "get",url: API_URL + queryStr,success: (data) => {
       console.log(data);
     },error: (err) => {
       console.log(error);
     },});
 }

解决方法

您可以使用2种不同的方法。

  1. 通过toLatLng方法返回承诺,例如:

function toLatLng(input) {
  return new Promise((resolve,reject) => {
    $.ajax({
      type: "get",url: GEOCODE_API_URL + input,datatype: "json",success: (data) => {
        if (data.status === "OK") {
          resolve(data.results[0].geometry.location);
        } else if (data.status === "ZERO_RESULTS") {
          reject("The search yielded no results");
        } else {
          reject("Unable to search for events");
        }
      },error: (error) => {
        reject(error);
      },});
  });
}

async function getEvents(input) {
  toLatLng(input).then(coordinates => {
    let queryStr = `&latlong=${coordinates.lat},${coordinates.lng}`
    $.ajax({
      type: "get",url: API_URL + queryStr,success: (data) => {
        console.log(data);
      },error: (err) => {
        console.log(error);
      },});
  }).catch(err => {
    console.log(err);
  });
}

  1. 将回调函数传递给toLatLng以在成功或失败时进行调用。

function toLatLng(input,successCallback,failureCallback) {
  $.ajax({
    type: "get",success: (data) => {
      if (data.status === "OK") {
        successCallback(data.results[0].geometry.location);
      } else if (data.status === "ZERO_RESULTS") {
        failureCallback("The search yielded no results");
      } else {
        failureCallback("Unable to search for events");
      }
    },error: (error) => {
      failureCallback(error);
    },});
}

function onCoardinateLoaded(coordinates) {
  let queryStr = `&latlong=${coordinates.lat},${coordinates.lng}`
  $.ajax({
    type: "get",success: (data) => {
      console.log(data);
    },error: (err) => {
      console.log(error);
    },});
}

function getEvents(input) {
  toLatLng(input,onCoardinateLoaded,onFailure);
}

function onFailure(message) {
  console.log(message);
}

,

您的代码中有几个错误。

  • 最重要的是,您希望能够await才能使用的功能需要返回承诺,或者本身就是async(技术上是同一件事)。您的geocode()函数既不是async也不返回任何东西,因此无法等待。
  • 接下来,您的geocode()函数返回值太具体了。不要使其返回“第一个结果”。使其返回 all 结果。调用代码可以决定是否只想使用第一个。这样,您的geocode()函数将变得更加通用。
  • 接下来,您的函数似乎正在使用原始查询字符串来手动构建URL。不要那样做传递对象(键/值)。 jQuery将在适当的时候将它们转换为查询字符串。
  • 如果您使用async / await,则应在某个时候使用try / catch
  • 接下来,您的功能可以精简很多。

改进的方法(为此,jQuery版本应为3.0或更高):

async function geocode(address) {
  var response = await $.get(GEOCODE_API_URL,{
    address: address,any: "other",parameters: "here",key: "YOUR_API_KEY"
  });
  if (response.status === "OK") return response.results;
  if (response.status !== "ZERO_RESULTS") console.log("geocode API status unexpected",response.status,response);
  return [];
}

async function getEvents(input) {
  var results = await geocode(input);
  if (!results.length) return;

  var coordinates = results[0].geometry.location;
  try {
    let data = await $.get(API_URL,{
      latlong: `${coordinates.lat},${coordinates.lng}`
    });
    console.log("getEvents SUCCESS",data);
  } catch (err) {
    console.log("getEvents ERROR",err);
  }
}