Iterate over an array when a forEach loop is running

I am trying to iterate over an array that I am creating from several HTTP calls inside angular.forEach()

function

 $scope.ticket_stats = function(){ //cleaning variables $scope.data_set = []; $scope.closed_tickets = []; //fetching time stamps (epoch) $scope.time_frame = time_period.days(7); //calling data using time stamps angular.forEach($scope.time_frame, function(item) { //debug console.log(item); var promise = tickets.status("closed", item); promise.success(function(data){ console.log(data); $scope.closed_tickets.push(data[0].datapoints[0][0]); // returns a numerical value }); }); //SEE MESSAGE BELOW $scope.data_set.push($scope.closed_tickets); } 

the last line of $scope.data_set.push() works, but increases over time as it accesses the data. I would like this line to be executed as soon as everything inside the cycle for each cycle is completed. I need to iterate over the $scope.closed_tickets to reproduce (add) the data inside it and create a second array.

The services used in this function are used here:

 // CALL TICKETS STATS app.service('tickets', function($http){ this.status = function(status, date){ var one_snap = date - 100; var url = "/url/render?format=json&target=sum(stats.tickets."+status+")&from="+one_snap+"&until="+date+""; return $http.get(url); }; }); // TIME STAMPS MATHS app.service('time_period', function(){ var currentDate = parseInt((new Date).getTime()/1000); this.days = function(number){ var pending = []; for (var i = number; i > 0; i--) { pending.push(currentDate - (87677*i)); } return pending; }; }); 

I searched for information and found out about the $q.all() , but I couldn’t complete this work the way I want.

Any advice would be welcome! Thanks!

+7
arrays angularjs foreach
source share
3 answers

You can use $ q.all to wait for the completion of several non-synchronous events (promises).

 $scope.ticket_stats = function() { // list of all promises var promises = []; //cleaning variables $scope.data_set = []; $scope.closed_tickets = []; //fetching time stamps (epoch) $scope.time_frame = time_period.days(7); //calling data using time stamps angular.forEach($scope.time_frame, function(item) { // create a $q deferred promise var deferred = $q.defer(); //debug console.log(item); tickets.status("closed", item).success(function(data) { console.log(data); $scope.closed_tickets.push(data[0].datapoints[0][0]); // promise successfully resolved deferred.resolve(data); }); // add to the list of promises promises.push(deferred.promise); }); // execute all the promises and do something with the results $q.all(promises).then( // success // results: an array of data objects from each deferred.resolve(data) call function(results) { $scope.data_set.push($scope.closed_tickets); }, // error function(response) { } ); } 

First, deferred represents a piece of code that will execute an unknown amount of time to execute (asynchronous). deferred.resolve(data) simply states that the code is complete. The data can be any, objects, strings, any, but usually it is the result of your asynchronous code. In the same way, you can reject a promise with deferred.reject(data) (maybe the error was thrown by the server). Again, the data can be anything, but there should probably be an answer to the error.

deferred.promise just returns a promise object. The Promise object allows you to set .then(successFunction, errorFunction) so that you know that part of the code has finished executing before proceeding to successFunction (or errorFunction if it fails). In our case, $q has a .all method, which waits for the promises array to complete, then gives the results of all promises as an array.

Remember to enter the $q service.

+21
source share

Try to make only an array of promises, but not resolving them. Then sum them up with $ q.all (). Once aggregated promises are allowed to iterate through an array of these promises. Now you are sure that they are all resolved.

 var promises = []; angular.forEach($scope.time_frame, function(item) { promises.push(tickets.status("closed", item)); }); var aggregatedPromise = $q.all(promises); aggregatedPromise.success(function(){ angular.forEach(promises, function(promise) { promise.success(function(data){ $scope.closed_tickets.push(data[0].datapoints[0][0]); // returns a numerical value }); }); }); 

This may not be the most efficient way to do this, but I think this should solve your problem.

+1
source share

Even if you mentioned that $ q.all doesn’t work for you, since I don’t understand why this is not, here is how I will do it.

Basically you want to map an array of things (timestamps) with some other things (promises in this case, since we have asynchronous calls) and perform some actions with the resulting array.

 var promises = $scope.time_frame.map(function (item) { return tickets.status("closed", item); }); 

Now we use $q.all to wait for all promises to solve:

 $q.all(promises).then(function (tickets) { $scope.data_set.push(tickets); }); 
+1
source share

All Articles