John
John

Reputation: 1717

Request Javascript/Angular running into problems with Async stuff

I've got some code that does the following.... The first get call basically just gives a list of posts in data. Then for each post, there are a number of replies which I would like to load given by the second get call. The problem is, it actually goes through the loop but then only loads the last reply.

 http.get("../api/sortpost/trending").success(function (data){
            scope.posts = data;
            for(var i = 0; i < scope.posts.length; i++){
              post=scope.posts[i];
              console.log(i); //prints 1 to i as expected
              http.get("/api/postreply/"+post.id).success(function (data){
                post.replies = data;
                console.log(i); //prints i only i number of times
              });
            }
      });

Anyone know how to fix? I am guessing that I am looping too quickly through and that the get request does not have enough time to process. Thus something funny is happening with my post.replies and i and the post is changing before the request is actually complete.

Upvotes: 0

Views: 49

Answers (2)

Piyush.kapoor
Piyush.kapoor

Reputation: 6803

Your post { post=scope.posts[i];} is getting modified on each item of the loop. The resulting post will be the last item in the array scope.posts ie. post = {some last one}

Thats why you are only seeing one post request since angular caches the post requests with the same url.

This is happening because your loop would run and get requests would be queued since javascript is single threaded. After your loop gets over all the $http.get will see the same value ie last value of post through clousers.

You can use Immediately invoked functions to tackle this problem.

    (function(myPost){
                 http.get("/api/postreply/"+myPost.id).success(function (data){
                    post.replies = data;
                    console.log(i); //prints i only i number of times
                  });
    })(post);

Upvotes: 1

ms87
ms87

Reputation: 17492

elclanrs comment correctly addresses the problem, you could try to make a promises array and execute them all at once and then get a list of all the results at once:

 var promisesArray=[];
 for(var i = 0; i < scope.posts.length; i++) {
        post=scope.posts[i];
        console.log(i); //prints 1 to i as expected
        promisesArray.push(http.get("/api/postreply/"+post.id));
 }

And then:

$q.all(promisesArray).then(function(aggregateData){
   console.log(aggregateData);
})

Upvotes: 2

Related Questions