greg greg - 1 month ago 17
AngularJS Question

How can I wait for $http response before continuing with angular.forEach loop

I'm making an AJAX request for each item in a loop, the end REST service can only perform one request at a time so I need the loop to wait for each request to complete before continuing with the next. How do I do this?

For reference, the end service is performing update tasks on DynamoDB tables - only one table can be modified at once hence my requirement to wait until I get a response before continuing. I could send them all to the server in one hit and handle there, although that makes it hard to receive feedback when each update is completed.

angular.forEach($scope.someArray,
function (value) {

var postdata = {
bla: value
};

$http.post('/some_url', postdata)
.then(
function(result) {
console.log("Success.");
},
function(data) {
console.log("Failure.");
}
);

}
);

Answer Source

If you really must make one request at a time (are you sure there isn't a more efficient alternative?), then you'll have to use something other than Angular.forEach.

What about something like this (you will need to inject $q):

function doWhateverWithAll(someArray) {
  // Mark which request we're currently doing
  var currentRequest = 0;
  // Make this promise based.
  var deferred = $q.deferred();
  // Set up a result array
  var results = []
  function makeNextRequest() {
    // Do whatever you need with the array item.
    var postData = someArray[currentRequest].blah;

    $http.post('some/url', postData)
    .then( function (data){
      // Save the result.
      results.push(data);
      // Increment progress.
      currentRequest++;
      // Continue if there are more items.
      if (currentRequest < someArray.length){
        makeNextRequest();
      }
      // Resolve the promise otherwise.
      else {
        deferred.resolve(results);  
      }  
    });
    // TODO handle errors appropriately.
  }
  // return a promise for the completed requests
  return deferred.promise;
}

Then, in your controller/service, you can do the following:

doWhateverWithAll($scope.someArray)

.then(function(results){
  // deal with results.
});