2014-08-27 27 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