$q.all() 在 Angularjs 中多次调用
$q.all() multiple calls in Angularjs
我有一个调用点击事件的函数。它有一个驱动程序列表,我希望通过 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) 您正在执行多项异步操作,但您只有一个延迟对象,所有对象都在使用该对象。因此,一旦他们中的任何一个解决了延迟,他们就会有效地全部解决。相反,他们每个人都需要自己的。
2) GetDriverMatrix 似乎在同时执行回调方法和承诺方法。只选一个(我推荐 promises)。
那么让我们从修复 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 的回调部分,我们将改用 promise。
2) 将 promises 数组放在函数内部,而不是外部。没有其他人需要看到这个数组,所以没有必要公开它
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) {
});
}
我有一个调用点击事件的函数。它有一个驱动程序列表,我希望通过 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) 您正在执行多项异步操作,但您只有一个延迟对象,所有对象都在使用该对象。因此,一旦他们中的任何一个解决了延迟,他们就会有效地全部解决。相反,他们每个人都需要自己的。
2) GetDriverMatrix 似乎在同时执行回调方法和承诺方法。只选一个(我推荐 promises)。
那么让我们从修复 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 的回调部分,我们将改用 promise。
2) 将 promises 数组放在函数内部,而不是外部。没有其他人需要看到这个数组,所以没有必要公开它
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) {
});
}