我有一个在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()的函数在回调响应之前触发。我在这做错了什么?我是新的承诺。
答案 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) {
});
}