AngularJS 的 $q.all 仅适用于一个结果
$q.all of AngularJS only works for one result
我正在研究在 Google 距离矩阵的帮助下计算从给定对象到许多其他地方的距离的函数,这当然是异步的,因此我正在处理承诺。
当位置数为一个时,一切都很好。但是一旦我有一个以上的承诺,$q.all 就不会做任何事情:它既不会成功也不会出错。虽然我已经在控制台中检查了对 Google 距离矩阵的调用确实发生并且 return 是正确的结果。有什么线索可以在这里发挥作用吗?
我正在使用 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;
});
不起作用的原因
当服务调用解析并调用回调处理程序时,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;
});
你的问题是 var
不是块范围的,所以 deferred
的值将始终属于你的任何回调被调用时循环的最后一次迭代。这样做的结果是,较早的延迟将永远不会得到解决,并且 $q.all
将出现挂起。
解决此问题的最简单方法是将 var
的使用更改为 let
以利用块范围:
let deferred = $q.defer();
我正在研究在 Google 距离矩阵的帮助下计算从给定对象到许多其他地方的距离的函数,这当然是异步的,因此我正在处理承诺。
当位置数为一个时,一切都很好。但是一旦我有一个以上的承诺,$q.all 就不会做任何事情:它既不会成功也不会出错。虽然我已经在控制台中检查了对 Google 距离矩阵的调用确实发生并且 return 是正确的结果。有什么线索可以在这里发挥作用吗?
我正在使用 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;
});
不起作用的原因
当服务调用解析并调用回调处理程序时,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;
});
你的问题是 var
不是块范围的,所以 deferred
的值将始终属于你的任何回调被调用时循环的最后一次迭代。这样做的结果是,较早的延迟将永远不会得到解决,并且 $q.all
将出现挂起。
解决此问题的最简单方法是将 var
的使用更改为 let
以利用块范围:
let deferred = $q.defer();