Reputation: 6213
I have the following function that gets executed from an ng-click
in the HTML:
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);
});
});
};
Now, the problem is that the vm.reload()
is executed after every successful response where in fact it would be enough if it was executed once after the entire forEach
finishes. I'm very new to async programming in JS so would like to know what the most used way to solve this is.
Upvotes: 0
Views: 1431
Reputation: 26
Solution:
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() })
});
Upvotes: 0
Reputation: 17578
Create an array where you store the promises from your HTTP calls. Afterwards call the Promise.all()
method. This allows you to do stuff when all promises are finished.
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();
});
};
Edit: Since you are using AngularJS, you can also do $q.all()
.
Upvotes: 2
Reputation: 5957
Move the vm.reload() outside the forEach loop:
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();
};
Edited to add $timeout, should give it enough time to finish the foreach loop.
Upvotes: -1
Reputation: 3232
You could do something like this:
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);
});
});
};
Upvotes: 0