Javascript 在forEach在Angular中完成后执行命令
我在HTML中通过ng单击执行以下函数:Javascript 在forEach在Angular中完成后执行命令,javascript,angularjs,asynchronous,Javascript,Angularjs,Asynchronous,我在HTML中通过ng单击执行以下函数: vm.items = []; vm.moveItems = function() { angular.forEach(vm.items, function (item) { $http({ method: 'PUT', url: '/api/item_move/' + item.id} }).then(function(
vm.items = [];
vm.moveItems = function() {
angular.forEach(vm.items,
function (item) {
$http({
method: 'PUT',
url: '/api/item_move/' + item.id}
}).then(function(response) {
Toast.success("Successfully moved item " + item.id);
vm.reload();
}, function (error) {
Toast.error("Failed to move item " + item.id, error);
});
});
};
现在,问题是vm.reload是在每次成功响应之后执行的,实际上,如果在整个forEach完成之后执行一次就足够了。我对JS中的异步编程非常陌生,因此想知道解决这个问题最常用的方法是什么。将vm.reload移到forEach循环之外:
vm.items = [];
vm.moveItems = function() {
this._$timeout(() => {
angular.forEach(vm.items,
function (item) {
$http({
method: 'PUT',
url: '/api/item_move/' + item.id}
}).then(function(response) {
Toast.success("Successfully moved item " + item.id);
}, function (error) {
Toast.error("Failed to move item " + item.id, error);
});
});
});
vm.reload();
};
编辑为添加$timeout,应该给它足够的时间来完成foreach循环。您可以这样做:
vm.items = [];
vm.moveItems = function() {
var i = 0
angular.forEach(vm.items,
function (item) {
$http({
method: 'PUT',
url: '/api/item_move/' + item.id}
}).then(function(response) {
Toast.success("Successfully moved item " + item.id);
i++;
if(i == vm.items.length{ // execute only when its the last loop of foreach
vm.reload();
}
}, function (error) {
i++;
if(i == vm.items.length{ // execute only when its the last loop of foreach
vm.reload();
}
Toast.error("Failed to move item " + item.id, error);
});
});
};
创建一个数组,在其中存储来自HTTP调用的承诺。之后调用Promise.all方法。这允许你在完成所有承诺后做一些事情
vm.items = [];
vm.moveItems = function() {
var promises = [];
angular.forEach(vm.items,
function (item) {
promises.push($http({
method: 'PUT',
url: '/api/item_move/' + item.id}
}));
});
Promise.all(promises)
.then(function() {
vm.reload();
});
};
编辑:因为您使用的是AngularJS,所以还可以执行$q.all。解决方案:
vm.items = [];
vm.moveItems = function() {
var promises = [];
angular.forEach(vm.items , function(item) {
var promise = $http({
method: 'PUT',
url: '/api/item_move/' + item.id}
}).then(function(response) {
Toast.success("Successfully moved item " + item.id);
}, function (error) {
Toast.error("Failed to move item " + item.id, error);
});
promises.push(promise);
});
$q.all(promises).then(function() { vm.reload() })
});
我认为这不管用,是吗?forEach中的请求将触发,代码将在请求实际完成之前继续重新加载,不是吗?这不起作用,因为HTTP调用需要一些时间才能完成。在请求完成之前调用vm.reload。编辑为添加$timeout调用,应该允许http调用完成。完美!我假设这是一个通用的JS解决方案。我看到Angular有一个$q构造函数。使用它还是使用简单的JS解决方案更好?@mart1n是的,它是ES6中添加的JS解决方案。$q也有可能看到使用$q更好。所以s/PROMITE/$q/是唯一的改变吗?@mart1n正是这样。