Angular.JS 循环保持 运行 而循环内的服务调用正在等待承诺
Angular.JS loop keeps running while a service call inside the loop is waiting for promise
"AddDistance" 是一个插入到数据库的函数,
问题是 hash[k][2] 值随着循环向前跳转,而 "distance"(服务承诺)仍在等待,结果我向我的数据库插入了错误的行。
我如何在 "AddDistance()" 运行 之前保持跳转到下一个对象的循环,我应该使用 Q$、While、.then() 吗?
我尝试了上面的方法但失败了,可能是没有做对。
请指教...
for (var k in hash)
{
GoogleMaps(hash[k][0], hash[k][1], function (x) {
var distance = x.rows[0].elements[0].distance.value;
distance = parseInt(distance / 1000);
AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
console.log(distance);
//return distance;
});
}
您可以执行如下操作,但它不会保持循环:
var loopPromises = [];
var distanceList = [];
for (var k in hash) {
var deferred = $q.defer();
loopPromises.push(deferred.promise);
//sample of a long-running operation inside loop...
distanceList[k] = GoogleMaps(hash[k][0], hash[k][1], function (x) {
var distance = x.rows[0].elements[0].distance.value;
distance = parseInt(distance / 1000);
AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
console.log(distance);
//return distance;
deferred.resolve(distance);
});
};
$q.all(loopPromises).then(function () {
console.log('forEach loop completed. Do Something after it...');
//use the distanceList here
});
请注意,只要下一次迭代不依赖于上一次迭代,此方法就可以正常工作。
您可以通过将 promise 链接在一起而不是 运行ning 并行地确保 运行ning 操作一次一个 运行 。但需要注意确保参数正确传递,因为循环将在任何 long-running 函数被调用之前完成。
因为函数是按顺序执行的,所以您可以将结果存储在数组中并确保它们是有序的。
var promise = $q.resolve();
var distances = [];
for (var k in hash) {
promise = chainPromise(promise, callGoogleMaps, k);
};
promise.then(function () {
console.log('forEach loop completed. Do Something after it...',
distances);
});
function chainPromise(promise, fn, k) {
return promise.then(function() { return fn(k); });
}
function callGoogleMaps(k) {
return $q(function(resolve) {
//sample of a long-running operation inside loop...
GoogleMaps(hash[k][0], hash[k][1], function (x) {
var distance = x.rows[0].elements[0].distance.value;
distance = parseInt(distance / 1000);
AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
console.log(distance);
distances.push(distance);
resolve();
});
});
}
"AddDistance" 是一个插入到数据库的函数, 问题是 hash[k][2] 值随着循环向前跳转,而 "distance"(服务承诺)仍在等待,结果我向我的数据库插入了错误的行。
我如何在 "AddDistance()" 运行 之前保持跳转到下一个对象的循环,我应该使用 Q$、While、.then() 吗?
我尝试了上面的方法但失败了,可能是没有做对。
请指教...
for (var k in hash)
{
GoogleMaps(hash[k][0], hash[k][1], function (x) {
var distance = x.rows[0].elements[0].distance.value;
distance = parseInt(distance / 1000);
AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
console.log(distance);
//return distance;
});
}
您可以执行如下操作,但它不会保持循环:
var loopPromises = [];
var distanceList = [];
for (var k in hash) {
var deferred = $q.defer();
loopPromises.push(deferred.promise);
//sample of a long-running operation inside loop...
distanceList[k] = GoogleMaps(hash[k][0], hash[k][1], function (x) {
var distance = x.rows[0].elements[0].distance.value;
distance = parseInt(distance / 1000);
AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
console.log(distance);
//return distance;
deferred.resolve(distance);
});
};
$q.all(loopPromises).then(function () {
console.log('forEach loop completed. Do Something after it...');
//use the distanceList here
});
请注意,只要下一次迭代不依赖于上一次迭代,此方法就可以正常工作。
您可以通过将 promise 链接在一起而不是 运行ning 并行地确保 运行ning 操作一次一个 运行 。但需要注意确保参数正确传递,因为循环将在任何 long-running 函数被调用之前完成。
因为函数是按顺序执行的,所以您可以将结果存储在数组中并确保它们是有序的。
var promise = $q.resolve();
var distances = [];
for (var k in hash) {
promise = chainPromise(promise, callGoogleMaps, k);
};
promise.then(function () {
console.log('forEach loop completed. Do Something after it...',
distances);
});
function chainPromise(promise, fn, k) {
return promise.then(function() { return fn(k); });
}
function callGoogleMaps(k) {
return $q(function(resolve) {
//sample of a long-running operation inside loop...
GoogleMaps(hash[k][0], hash[k][1], function (x) {
var distance = x.rows[0].elements[0].distance.value;
distance = parseInt(distance / 1000);
AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
console.log(distance);
distances.push(distance);
resolve();
});
});
}