我想使用这样的承诺来调用Google Maps Geocoding API:
function makeGeoCodingRequest(address,bounds)
{
/*
Input parameters:
address:a string
bounds: an object of class google.maps.LatLngBounds(southWest,northEast)
This will return a set of locations from the google geocoding library for the given query
*/
var url="https://maps.googleapis.com/maps/api/geocode/json?address=" + address + "&key=AIzaSyD9GBloPC20X-1kWRo7sm_0z5xvCiaSd3c";
var promise,response;
var messages={
"ZERO_RESULTS":"No results were found",
"OVER_QUERY_LIMIT":"We are over the query limit.Wait awhile before making a request",
"REQUEST_DENIED":"Request was denied,probably using a bad or expired API Key",
"INVALID_REQUEST":"Request was sent without the required address,component or component",
"UNKNOWN_ERROR": "There was an error somewhere on Google's servers"
};
if(address)
promise=Q($.ajax({
type: "GET",
url: "https://maps.googleapis.com/maps/api/geocode/json?address=" + address + "&key=API_KEY"
}));
return promise.then(function(data) {
if (data.status === "OK") return data;
else console.error(messages[data.status]);
return null;
});
}
当我调用函数makeGeoCodingRequest
请求时,我发现我获得了一个承诺而不是一个值:
var geo=makeGeoCodingRequest(address);
console.log(Q.isPromise(geo));//returns true
为什么没有promise.then在返回值之前执行?我怎样才能从这个承诺中获得价值而不是另一个承诺?
答案 0 :(得分:6)
如果您依赖承诺以返回数据,则必须从函数返回承诺。
如果你的callstack中的1个函数是异步的,那么想要调用它的所有函数也必须是异步的,如果你想继续线性执行的话。 (async =返回一个承诺)
请注意,您的if
语句没有大括号,因此只有条件失败后才会执行第一个语句。
我在这个例子中修复了它。请注意我添加的评论。
if(address){
promise=Q($.ajax({
type: "GET",
url: "https://maps.googleapis.com/maps/api/geocode/json?address=" + address + "&key=API_KEY"
}));
return promise.then(function(data) {
// whatever you return here will also become the resolve value of the promise returned by makeGeoCodingRequest
// If you don't want to validate the data, you can in fact just return the promise variable directly
// you probably want to return a rejected promise here if status is not what you expected
if (data.status === "OK") return data;
else console.error(messages[data.status]);
return null;
});
}
您必须以下列方式致电makeGeoCodingRequest
。
makeGeoCodingRequest(address,bounds).then(function(data){
// this will contain whatever
console.log(data);
});
答案 1 :(得分:3)
我发现我获得了承诺而不是值
是的,因为操作是异步的,并返回表示未来值的promise。
为什么不承诺。然后在返回值之前执行?
因为它是异步的。 .then
{({3}})将在返回另一个promise之前永远不会执行其回调。
如何从此承诺中获取值而不是另一个承诺?
您在回调中获得了值:
makeGeoCodingRequest(address).then(function(geo) {
console.log(geo)
console.log(Q.isPromise(geo)); // false
// do anything with the value here
})
// if you need to do anything with the result of the callback computation:
// you're getting back another promise for that!
从承诺(must)同步获取它是不可能的。这意味着阻止执行,这是我们不想要的 - 让我们保持异步和非阻塞!
答案 2 :(得分:0)
您正在从函数makeGeoCodingRequest返回一个promise。根据我的说法,这是一件好事,如果将来需要,这可以帮助您链接任何更多的异步调用。我建议在返回的promise上使用.then(),并按以下方式检查promise是否有任何返回值或错误。
var geoPromise = makeGeoCodingRequest(address);
geoPromise.then(
onSuccess(result){
// You can use the result that was passed from the function here..
},
onFailure(response){
// Handle the error returned by the function.
}
);
答案 3 :(得分:-1)
如果您希望代码在继续之前等待异步操作完成(BAD IDEA - 请求完成时页面将冻结),则将async: false
添加到ajax请求的参数中。
我的建议是让makeGeoCodingRequest
不直接返回任何内容 - 只需给它一个额外的参数requestCallback
,这样它的调用者就可以传入一个函数,当数据是可用。使用结果数据在promise.then
函数内调用该函数。