$ q.all AngularJS仅适用于一个结果

时间:2017-06-08 14:08:37

标签: angularjs angular-promise q

我正在开发函数,在Google Distance Matrix的帮助下计算从给定对象到其他一些地方的距离,这当然是异步的,因此我处理的是承诺。

当地方数量为1时,一切都很好。但是,一旦我有一个以上的承诺,$ 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;
});

2 个答案:

答案 0 :(得分:2)

您的问题是var不是块范围的,因此在调用任何回调时,deferred的值将始终属于循环的最后一次迭代。这样做的结果是,先前的延迟将永远不会被解决,$q.all似乎会挂起。

解决此问题的最简单方法是将var的使用更改为let以利用块范围:

let deferred = $q.defer();

答案 1 :(得分:1)

无效的原因

当服务调用解析并调用回调处理程序时,deferred属性指的是for循环创建的最后一个延迟对象。因此,实际上,您始终在最后创建的resolve对象上执行deferred

<强>解决方案:

创建一个新功能:

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;
});