$ q.all()Angularjs

时间:2017-10-02 15:03:15

标签: javascript angularjs angular-promise

我有一个在click事件上调用的函数。它有一个驱动程序列表,我希望通过Google方向服务对每个驱动程序进行ETA。这是我的代码:

var deferred = $q.defer();
var urlCalls = [];

function getDriversEta(jobLoc, drivers) { //this function gets invoke on click.
    angular.forEach(drivers, function (value, key) {
        value.eta = undefined;
        urlCalls.push(GetDriverMatrix(jobLoc.lat, jobLoc.lon,
            value.Location.Latitude, value.Location.Longitude, function (response) {
                value.eta = formatSecondsToTime(response.routes[0].legs[0].duration.value);
                deferred.resolve(value);
            }));
    });
    $q.all(urlCalls).then(
        function (results) {
            var check = results;
        },
        function (errors) {
            //deferred.reject(errors);
        },
        function (updates) {
            //deferred.update(updates);
        });
}

function GetDriverMatrix(pickupLat, pickupLon, driverLat, driverLon, callBack) {
    var directionsService = new google.maps.DirectionsService();
    var directionsRequest = {
        origin: new google.maps.LatLng(driverLat, driverLon),
        destination: new google.maps.LatLng(pickupLat, pickupLon),
        travelMode: google.maps.DirectionsTravelMode.DRIVING,
        unitSystem: google.maps.UnitSystem.METRIC
    };
    directionsService.route(directionsRequest, function (response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            callBack(response);
        }
    });

    return deferred.promise;
}

它第一次工作正常,但提供重复值。但是在第二次单击事件中,$ q.all()的函数在回调响应之前触发。我在这做错了什么?我是新的承诺。

1 个答案:

答案 0 :(得分:3)

你有几个问题:

1)您正在执行多个异步操作,但您只有一个延迟对象,所有这些对象都在使用。因此,只要他们中的任何一个解决了延期,他们就会有效地解决所有问题。相反,他们每个人都需要自己的 2)GetDriverMatrix似乎同时进行回调方法和承诺方法。只挑一个(我推荐承诺)。

所以让我们从修复GetDriveMatrix开始:

//** Callback parameter removed
function getDriverMatrix(pickupLat, pickupLon, driverLat, driveLon) {
    var deferred = $q.defer(); //** create a new deferred each time
    var directionsService = new google.maps.DirectionsService();
    var directionsRequest = {
        origin: new google.maps.LatLng(driverLat, driverLon),
        destination: new google.maps.LatLng(pickupLat, pickupLon),
        travelMode: google.maps.DirectionsTravelMode.DRIVING,
        unitSystem: google.maps.UnitSystem.METRIC
    };
    directionsService.route(directionsRequest, function (response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
        deferred.resolve(response); //** resolve instead of calling callback
    } else {
        deferred.reject(response); //** reject if there's an error
    }
    return deferred.promise;
});

现在使用它,你大部分都在正确的轨道上,但我会改变一些事情:

1)由于我删除了getDriverMatrix的回调部分,我们将使用该承诺。
2)将承诺数组放在函数内部,而不是在函数外部。没有人需要看到阵列,所以没有必要暴露它 3)我不使用foreach然后推入数组,而是使用array.map。它专为此类情况而设计,使您无需手动进行推送。

function getDriversEta(jobLoc, drivers) {
    //** Using array.map to produce a new array of promises
    var promises = drivers.map(function (driver) {
        return GetDriverMatrix(jobLoc.lat, jobLoc.lon, driver.Location.latitude, driver.Location.longitude)
            //** using the .then method instead of callback
            .then(function (response) {
                driver.eta = formatSecondsToTime(response.routes[0].legs[0].duration.value);
                return driver;
            });
    });

    $q.all(promises).then(
        function (results) {
            var check = results;
        },
        function (errors) {

        },
        function (updates) {

        });
}