I would like to know if it's possible to use while
or for
with a nested call to $http.get
:
This is an example:
for (var i = 0; i < $scope.comments.length; i++) {
alert($scope.comments[i].id); // = 2
$http.get('/api/logged/like/isliked?id=' + $scope.comments[i].id).success(function(data, status, header, config) {
alert('Test');
alert($scope.comments[i].id); // Not executed.
}).error(function(data){alert('The requeste isn't working');}); }
I put two alert
s to display the id of my comment I'm using to retrieve JSON. I get the id with the first alert, then 'Test' for the second, but the third alert isn't displaying. Why not?
Here an example of the JSON:
{data":[
{"id":2,"is_liked":false,"nb_comments":1,"nb_likes":1,
"date_creation":"2014-05-26T17:03:54+0000"},
{"id":1,"is_liked":true,"nb_comments":0,"nb_likes":1,
"date_creation":"2014-05-26T17:00:26+0000"}
]}
The problem:
Don't make functions inside of a loop ...
Each call of your function is actually referencing the same copy of i
in memory. A new closure is created each time the for loop runs, but each one captures the same environment. Therefore, every call to $http.get
(an asynchronous function) results in the firing of a callback referencing the same final value of i
from the end of loop.
A solution:
Pass i
as a parameter to a separately defined function:
var getIsLiked = function(i){
$http.get('isliked.json' + $scope.comments[i].id)
.success(function(data) {
console.log('Test');
console.log('i is ', i);
console.log($scope.comments[i].id);
}).error(function(data){console.log("The request isn't working");}); }
}
for (var i = 0; i < $scope.comments.length; i++) {
getIsLiked(i);
}
Demo
This can be really hard to wrap your head around, but it's worth the time to understand deeply. Not only will it help you to avoid similar problems in the future, it will also give you a better understanding of closures, an important concept in JavaScript.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With