2014-08-27 84 views
7

我想打电话给使用无极这样的谷歌地图地理编码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?我如何从这个承诺中获得价值而不是另一个承诺?

回答

5

如果您依赖承诺来返回您的数据,则必须从您的函数中返回一个承诺。

一旦你的callstack中的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); 
}); 
+0

如果我拒绝使用'promise.then(...)'和'return promise',然后使用'makeGeoCodingRequest(address,bounds).then(...)',它会不会相同? – vamsiampolu 2014-08-27 15:15:49

+0

是的,'makeGeoCodingRequest'返回的promise与''promise.then'处理程序中的返回值具有相同的值。你可以通过返回类似'Q.reject(新错误(“Http请求失败”+ data.status))' – 2014-08-27 15:23:12

+1

谢谢你的答案,一切正常,包括Q.reject。 – vamsiampolu 2014-08-27 15:40:02

-1

如果您希望代码在继续之前等待异步操作完成(BAD IDEA - 页面在请求完成时冻结),则将async: false添加到ajax请求的参数中。

但是,我的建议是让makeGeoCodingRequest直接返回任何东西 - 并简单地给它一个额外的参数requestCallback,这样它的调用者可以传入一个函数,当数据可用时它将被调用。调用该函数,并将结果数据放入您的promise.then函数中。

+0

如果我的答案有问题,或许有人可以提出一个改进建议? – Katana314 2014-08-27 15:04:22

+0

您提出的进行同步请求的建议并未解决OP不了解承诺概念的事实。除此之外,这是错误的。你需要设置一个'async:false'来实现同步请求。就像你注意到你的自我,在几乎任何情况下,这是一个坏主意。在函数中引入一个回调也是一个坏主意,很明显'makeGeoCodingRequest'应该只是返回一个promise,混合这两个都是一个反模式,并且让初学者感到困惑。 – 2014-08-27 15:10:48

+0

啊,正确;我得到了异步值错误。这部分实际上是为了解释为什么他的代码不能简单地返回一个值。我想我并不熟悉哪些功能应该继续使用给定的“承诺”对象的意识形态,哪些功能应该转变为简单化的功能;所以这对我来说实际上是新的。我没有建议他应该同时使用两者。 – Katana314 2014-08-27 15:17:53

0

您正在从函数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. 
    } 
); 
3

我发现我得到一个承诺,而不是一个值

是的,这是因为操作是异步的,并返回它代表了未来价值的承诺。

为什么在返回值之前未执行promise.then?

因为它是异步的。 .thenmust)在它返回另一个承诺之前从不执行其回调。

我该如何从这个承诺中获得一个价值而不是另一个承诺?

您在回调所获得的价值:

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! 

这是不可能从承诺(many have tried)同步获取。这意味着阻止执行,我们不希望 - 让我们保持异步和非阻塞!

+0

很好解释。引用“如何从AJAX调用返回响应”以及与此问题有关的其他问题可能会很有趣。 – 2014-08-27 15:17:18

+0

你基本上说的是,你想做的任何事情必须在'then'方法内使用'data'来完成,'data'我在'callback'中作为'argument'获得。就像'callbacks'一样,我猜测。 – vamsiampolu 2014-08-27 15:46:55

+1

是的,[就像回调](http://stackoverflow.com/a/22562045/1048572)。只有你为回调的结果得到了另一个承诺,这使得它们可以链接。 – Bergi 2014-08-27 15:48:35