问题描述
我有一个使用地理编码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种不同的方法。
- 通过
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);
});
}
- 将回调函数传递给
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);
}
}