1

I am new to AngularJS and I am trying to send http request using .foreach loop. Here's my code

app.controller('myCtrl', function($scope, $http) {
var rd;
$http.get(furl,config).then(function mySucces(response) {
rd = response.data;
var webcontent = "";
angular.forEach(rd, function(rd1){
    $http.get(furl1 + rd1.slug,config).then(function(res){          
    webcontent += res.data.title;
    console.log(webcontent);//console 1
    });
});
console.log(webcontent);//console 2
$scope.myWelcome = webcontent;
}, function myError(response) {$scope.myWelcome = response.statusText;});});

I was expected the console 2 will display the combined "res.data.title", however, it only shows the initial value.(which is empty in this case). The console log 1 is showing correctly - list the increasing "webcontent" variable. Not sure how to keep the "webcontent" (console 2) updated value. Any response will be appreciated! Thanks!

1
  • Because Ajax calls are async and you cannot do what you're doing. Commented Apr 15, 2016 at 16:55

3 Answers 3

1

This isn't an angular problem, this is an asynchronous javascript problem. Your code finished before your promise completes. You could use the query library to wait for all the promises to resolve, like so:

app.controller('myCtrl', function($scope, $http, $q) {
    var rd;
    $http.get(furl, config).then(function mySucces(response) {
        rd = response.data;
        var webcontent = "";
        var promises = [];

        angular.forEach(rd, function(rd1) {
            promises.push($http.get(furl1 + rd1.slug, config);
        });

        $q.all(promises).then(function (results) {
            angular.forEach(results, function (result) {
                webcontent += result.data.title;
            }

            $scope.myWelcome = webcontent;
        });
    }, function myError(response) {
        $scope.myWelcome = response.statusText;
    });
});
Sign up to request clarification or add additional context in comments.

Comments

0

You could just remove the webcontent variable entirely and update the $scope.myWelcome variable directly in it's place, it should work then. So:

app.controller('myCtrl', function($scope, $http) {
var rd;
$http.get(furl,config).then(function mySucces(response) {
rd = response.data;
$scope.myWelcome = "";
angular.forEach(rd, function(rd1){
    $http.get(furl1 + rd1.slug,config).then(function(res){          
      $scope.myWelcome += res.data.title;
      console.log(webcontent);//console 1
    });
});


}, function myError(response) {$scope.myWelcome = response.statusText;});});

3 Comments

This only works if your AJAX calls complete in sequence. There's a high chance they'll come back out of order.
@MikeRobinson That's true but is it an issue to have them out of order in this case? and if so you could just create an array of objects containing the results and sort them however you want.
Consider he's generating a welcome message, I would say the order is quite important. It's hard to say whether you could resort the messages after the fact, since we don't know what's being returned. Regardless, you can bypass the whole ordering problem simply by using $q.all to maintain the order of requests.
0

Ajax Calls are always async tasks, they are something similar window.setTimeout. It is impossible to write your code task by task. have a look:

console.log(1);
window.setTimeout(console.log.bind(console, 2));
console.log(3);

This happens because async tasks are executed in subsequent event loops (in the future).


Finally, your snippet could be something like that:

$http
  .get(furl, config)
  .then(function(response) { return response.data; })
  .then(function(resources) {
    return $q.all(resources.map(function(resource) {
      return $http.get(furl1 + resource.slug, config);
    }));
  })
  .then(function(results) {
    return results.map(function(result) {
      return result.data.title;
    }).join('');
  })
  .catch(function(response) {
    return response.statusText;
  })
  .then(function(greetings) {
    $scope.myWelcome = greetings;
  })
;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.