Alexander Bondarenko
Alexander Bondarenko

Reputation: 207

Javascript closure access with callbacks inside loop

what shall I do to make the last row of code return a value?

$scope.runActionwithObjects = function() {

            for (var i = 0; i < $scope.Objects.length; i++) {
                console.log($scope.Objects[i]); //$scope is accessible
                $http.get($scope.Objects[i]["Commit"]).success(function (data) {
                    console.log($scope.Objects[i]);//return undefined

Upvotes: 0

Views: 448

Answers (2)

Khanh TO
Khanh TO

Reputation: 48972

The problem is due to asynchrony of ajax requests.

When the success callback is executed, your loop has already finished and the i variable is already equal to $scope.Objects.length.

Try forEach. This function will create different closures for items in the array.

$scope.Objects.forEach(function(currentObject){
    console.log(currentObject); //$scope is accessible
    $http.get(currentObject["Commit"]).success(function (data) {
        console.log(currentObject);
    });
});

Upvotes: 1

nhabuiduc
nhabuiduc

Reputation: 1008

The reason your $scope.Objects[i] is undefined because the variable i is always = $scope.Objects.lenth + 1, for example you got 5 elements, the i will be 6, because the at the time of callback, it already got the last value.

One solution is to bind needed object to that method, so we can access it via this(we can not reference directly by closure to ref variable, because it's still stored the last item), for example:

           for (var i = 0; i < $scope.Objects.length; i++) {
               var ref = $scope.Objects[i];
               // console.log($scope.Objects[i]); //$scope is accessible
               var successCallback = (function (data) {
                   console.log(this);//return the ref

               }).bind(ref);
               $http.get('').success(successCallback);
           }
       }

Upvotes: 1

Related Questions