Javascript 从承诺返回值
我想使用如下承诺调用Google地图地理编码API:Javascript 从承诺返回值,javascript,jquery,ajax,promise,q,Javascript,Jquery,Ajax,Promise,Q,我想使用如下承诺调用Google地图地理编码API: function makeGeoCodingRequest(address,bounds) { /* Input parameters: address:a string bounds: an object of class google.maps.LatLngBounds(southWest,northEast) This will return a
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
request时,我发现我得到的是一个承诺而不是一个值:
var geo=makeGeoCodingRequest(address);
console.log(Q.isPromise(geo));//returns true
为什么不在返回值之前执行promise?如何从这个承诺而不是另一个承诺中获得值?如果希望代码等到异步操作完成后再继续(坏主意-请求完成时页面将冻结),则将
async:false
添加到ajax请求的参数中
不过,我的建议是让
makeGeoCodingRequest
不直接返回任何内容,只需给它一个额外的参数,requestCallback
,这样它的调用者就可以传入一个函数,当数据可用时将调用该函数。在承诺内调用该函数,并使用生成的数据。然后
函数。您将从函数makeGeoCodingRequest返回承诺。我认为这是一件好事,如果将来需要,这可以帮助您链接更多的异步调用。我建议对返回的承诺使用.then(),并按以下方式检查该承诺是否有任何返回值或错误
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.
}
);
如果为了返回数据而依赖于承诺,则必须从函数返回承诺 一旦调用堆栈中的1个函数是异步的,如果要继续线性执行,所有要调用它的函数也必须是异步的。 (异步=返回承诺) 请注意,
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);
});
我发现我得到的是承诺而不是价值
是的,因为该操作是异步的,并且返回一个表示未来值的承诺
为什么不在返回值之前执行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!
从promise()同步获得它是不可能的。这意味着阻塞执行,这是我们不想要的——让我们保持异步和非阻塞 如果我的回答有问题,也许有人可以提出改进的建议?您提出的同步请求的建议并没有解决OP不理解承诺概念这一事实。除此之外,这是错误的。您需要设置一个
async:false
,以实现同步请求。就像你注意到自己一样,在几乎任何情况下,这都是个坏主意。在函数中引入回调也是一个坏主意,因为显然makeGeoCodingRequest
应该只返回一个承诺,将两者混合使用是一种反模式,对初学者来说是一种困惑;我把异步值弄错了。这一部分实际上是解释为什么他的代码不能简单地返回一个值。我想我个人并不熟悉这样的意识形态:哪些功能应该继续使用给定的“承诺”对象,哪些应该转换为简单化的功能;所以这对我来说是新的。我没有建议他两者都用。你的答案仍然是建议他两者都用。不,不是。请仔细阅读。第一段以“如果你想让你的代码等待…”开头,也表示这是个坏主意。第二段是另一段。如果我决定使用promise。然后(…)
和返回promise
,然后使用makeGeoCodingRequest(地址,边界)。然后(…)
,它还会是一样的吗?是的,makeGeoCodingRequest
返回的承诺将与承诺中的返回值具有相同的值。然后
处理程序。您可以通过返回类似Q.reject(新错误(“Http请求失败”+data.status))
谢谢您的回答,一切正常,包括Q.reject。解释得很好。参考“如何从AJAX调用返回响应”以及与此问题相关的其他问题可能会很有趣。您的基本意思是,您想做的任何事情都必须在然后方法中完成,使用数据作为参数在回调中获取我想,就像回调一样。是的。只不过你得到了回调结果的另一个承诺,这使它们成为可链接的。你还得到了免费抛出统一错误处理的可能性。承诺不给出值,而是使用将要使用该值的函数传递到承诺中。然后()