2017-06-08 26 views
2

我正在計算從給定對象到許多其他地方的距離的函數,藉助Google距離矩陣當然是異步的,因此我正在處理與承諾。

當地方的數量是一個,一切都很好。但是,一旦我有一個以上的承諾,$ q.all不會做任何事情:既不能成功,也不會失敗。雖然我已經在控制檯檢查了Google距離矩陣的調用確實發生並返回了正確的結果。任何線索可以在這裏玩什麼?

我正在使用AngularJS 1.6.4。讓我知道你是否需要更多的細節。謝謝!

var requests = []; 
for (var i = 0; i < ctrl.places.length; i += 1) { 
    var deferred = $q.defer(); 
    requests.push(deferred.promise); 
    var destination = ctrl.places[i].latLng; 
    service.getDistanceMatrix({ 
     origins: [ctrl.origin], 
     destinations: [destination[0] + "," + destination[1]], 
     travelMode: 'DRIVING' 
    }, function(response, status) { 
     if (status === 'OK') { 
      deferred.resolve(response.rows[0].elements[0].distance.text); 
     } 
    }); 
} 

$q.all(requests).then(function(result) { 
    ctrl.distances = result; 
}); 

回答

1

它之所以不起作用

通過服務調用解析和回調處理程序被調用時,deferred屬性指的是由for環產生的最後延期的對象。因此,實際上,您始終在創建的最後一個deferred對象上執行resolve

解決方案:

創建一個新的功能:

function getDistanceMatrixForDestination (destination, origins) { 
    var deferred = $q.defer(); 
    service.getDistanceMatrix({ 
     origins: [origins], 
     destinations: [destination[0] + "," + destination[1]], 
     travelMode: 'DRIVING' 
    }, function(response, status) { 
     if (status === 'OK') { 
      deferred.resolve(response.rows[0].elements[0].distance.text); 
     } else { 
      deferred.reject(); 
     } 
    }); 
    return deferred.promise; 
} 

現有代碼改成這樣:

var requests = []; 
for (var i = 0; i < ctrl.places.length; i += 1) { 
    var destination = ctrl.places[i].latLng; 
    requests.push(getDistanceMatrixForDestination (destination, ctrl.origins)); 
} 

$q.all(requests).then(function(result) { 
    ctrl.distances = result; 
}); 
+0

工作就像一個魅力!非常感謝!花了幾個小時對此進行了討論! – Nat

2

您的問題是var沒有阻止範圍的,所以在任何回調函數中,deferred的值將始終屬於循環的最後一次迭代重新調用。這樣做的結果是,較早的延期將永遠不會被解決,並且$q.all似乎會掛起。

解決這個最簡單的方法是改變你的varlet使用取塊作用域的優勢:

let deferred = $q.defer(); 
+0

我喜歡你的方案範圍解決方案。很簡單。但是,你不覺得瀏覽器支持會成爲一個問題嗎? – CodeWarrior