如何在恢复函数执行之前等待承诺解决

How to wait for promise to resolve before resuming function execution

我有一个使用地理编码 api 将字符串 (address/zip/city) 转换为坐标的函数。我有另一个函数需要坐标 return 从地理编码 api 调用不同的 api 来搜索事件。但是,我是异步 javascript 的新手,我在使用 async/await 时遇到了麻烦。事件 api 表示地理编码 api 中应 return 的坐标未定义,但几秒钟后,坐标被 return 编辑。我需要事件 api 停止执行,直到从地理编码 api 中编辑坐标 return。有人可以给我指出正确的方向吗?

这是两个函数的代码

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,
     datatype: "json",
     success: (data) => {
       console.log(data);
     },
     error: (err) => {
       console.log(error);
     },
   });
 }

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

  1. Return 来自 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,
      datatype: "json",
      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",
    url: GEOCODE_API_URL + input,
    datatype: "json",
    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",
    url: API_URL + queryStr,
    datatype: "json",
    success: (data) => {
      console.log(data);
    },
    error: (err) => {
      console.log(error);
    },
  });
}

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

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

您的代码中有几个错误。

  • 最重要的是,您希望能够 await 的函数需要 return 一个承诺,或者是 async 本身(从技术上讲,这是一回事)。您的 geocode() 函数既不是 async 也不是 return 任何东西,因此无法等待。
  • 接下来,您的 geocode() 函数 return 值太具体了。不要将它 return 作为“第一个结果”。使其成为 return 所有 结果。调用代码可以决定它是否只想使用第一个。这样你的 geocode() 函数就变得更加通用。
  • 接下来,您的函数似乎在传递原始查询字符串以手动构建 URL。不要那样做。传递对象 (key/value)。 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);
  }
}