1

I'm trying to create an Ionic app and for this I have to make some HTTP GET request inside a for loop but it appears that angular does not wait for the data before showing them.

Here is a code I'm using.

$http.get(ApiUrl.get() + '/Threads' + '?access_token=' + $scope.userToken + filterString + "&filter[order]=created%20desc")
.success(function(data, status, headers, config) {

    var i=0;

    for(thread in data)
    {
        $scope.threadObj = data[i];
        var threadId = $scope.threadObj.id;
        $scope.threadPostNumber;

        //On récupére chaque nombre de post
        $http.get(ApiUrl.get() + '/Threads/' + threadId + '/posts/count' + '?access_token=' + $scope.userToken)
            .success(function(data, status, headers, config) {
                $scope.threadPostNumber = data.count;
            })
            .error(function(data, status, headers, config) {
                alert("Connection error, please try again.");
                $location.path("/app/carte");
            });

        $scope.threadObj.count = $scope.threadPostNumber;
        $scope.threads[i] = $scope.threadObj;

        i++;
    }
})
.error(function(data, status, headers, config) {
    alert("Connection error, please try again.");
    $location.path("/app/carte");
});

The first HTTP get is done and the data can be show within the foreach but when I try to add additionnal data to the original ones with a second get request nothing is created or sometimes only the last value is shown for every one.

2
  • Sadly, you can't use $http like that. stackoverflow.com/a/17366158/3980115 Commented Feb 10, 2015 at 22:12
  • @Vlad274 and is there a way to do this without the localstorage? Commented Feb 10, 2015 at 22:15

1 Answer 1

3

The problem stems from the API call being asynchronous, and much slower than the for loop.

The $http.get posts the request, but it doesn't get the response until long after the for loop completes. As a consequence $scope.threadPostNumber inside the promise success callback is going to be set after it is assigned in:

$scope.threadObj.count = $scope.threadPostNumber

So effectively this assignment is useless.

In order to fix, use tail recursion or Promise objects in order to make the calls consecutive.

You can also properly scope the current thread object so that when the promise succeeds you will be modifying the correct thread:

$http.get(ApiUrl.get() + '/Threads' + '?access_token=' + $scope.userToken + filterString + "&filter[order]=created%20desc")
.success(function(data, status, headers, config) {

    data.forEach(function(thread, i) {

        $scope.threads[i] = thread;

        var threadId = thread.id;

        $http.get(ApiUrl.get() + '/Threads/' + threadId + '/posts/count?access_token=' + $scope.userToken)
            .success(function(data, status, headers, config) {

                $scope.threads[i].count = data.count;
            })
            .error(function(data, status, headers, config) {

                alert('Connetion error, please try again.');
                $location.path('/app/carte');
            });
    });
})
.error(function(data, status, headers, config) {
    alert("Connection error, please try again.");
    $location.path("/app/carte");
});

Because this uses forEach (see the MDN page), thread and i are scoped to the function, so for the lifetime of that function and any functions that it calls or creates (like the promise success callback), thread and i will remain the value passed into the function. This ensures that no matter what order the HTTP requests return in, you'll be setting count on the proper thread.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.