Monday, May 13, 2024
 Popular · Latest · Hot · Upcoming
184
rated 0 times [  187] [ 3]  / answers: 1 / hits: 50877  / 11 Years ago, tue, may 7, 2013, 12:00:00

How do I add a callback function after an async forEach Loop?



Here is some better context:



$scope.getAlbums = function(user, callback) {
$scope.albumsList.forEach(function (obj, i) {
$scope.getAlbum(user, obj.id, function(value){
$scope.albums.push(value);
});
});
// callback(); ???
};

$scope.getAlbums('guy123', function(){
// forEach loop is all done!
console.log($scope.albums)
});


Controller:



.controller('Filters', ['$scope','Imgur', function($scope, Imgur) {

$scope.getAlbum = function(user, id, callback) {
Imgur.album.get({user:user, id:id},
function(value) {
return callback(value.data);
}
);
}

$scope.getAlbums = function(user, callback) {
// Callback function at end of this forEach loop?
// Request is async...
$scope.albumsList.forEach(function (obj, i) {
$scope.getAlbum(user, obj.id, function(value){
$scope.albums.push(value);
});
});
};
)]};


Service:



.factory('Imgur', function($resource) {
return {
album : $resource('https://api.imgur.com/3/account/:user/album/:id')
}
});

More From » angularjs

 Answers
29

As Andrew said usage of $q and the deferred object should allow you to accomplish your goal.



You want to use $q.all() This will make sure all of your promise objects are resolved and then you can call your call back in .then()



function MyCtrl($scope, $q, $http) {

$scope.albumsList = [{
id: 1,
name: 11
}, {
id: 2,
name: 22
}
];
$scope.albums = [];
$scope.getAlbum = function(user, id, callback) {
return $http.get(https://api.imgur.com/3/account/ + user + /album/ + id).success(
function(value) {
return callback(value.data);
}
);
}
$scope.getAlbums = function (user, callback) {
var prom = [];
$scope.albumsList.forEach(function (obj, i) {
prom.push($scope.getAlbum(user, obj.id, function(value){
$scope.albums.push(value);
}));
});
$q.all(prom).then(function () {
callback();
});
};
$scope.getAlbums('guy123', function () {
alert($scope.albums.length);
});
}


Example with this on jsfiddle



Works but not with $http calls



With the deferred object you gain access to a promise where you can change successive then() calls together. When you resolve the deferred object it will execute the foreach and then execute your call back function you supplied. I tried to simplify your example a bit further so it would work in jsfiddle.



function MyCtrl($scope, $http, $q) {

$scope.albumsList = [{
id: 1,
name: 11
}, {
id: 2,
name: 22
}];
$scope.albums = [];
$scope.getAlbums = function (user, callback) {
var deferred = $q.defer();
var promise = deferred.promise;
promise.then(function () {
$scope.albumsList.forEach(function (obj, i) {
$scope.albums.push(obj);
});
}).then(function () {
callback();
});
deferred.resolve();
};
$scope.getAlbums('guy123', function () {
alert($scope.albums.length);
});
}


Example on jsfiddle



A bit more reading on deferred and promises.


[#78370] Monday, May 6, 2013, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jeremiahianx

Total Points: 629
Total Questions: 106
Total Answers: 112

Location: Djibouti
Member since Sun, Feb 27, 2022
2 Years ago
;