1

$http.get("./data/web.json") request succesfully and return a array. When I loop the array by doing request, the iterator variable i would be undefined?! So how can I access the return array and doing the loop request?

    <script>
        var ngApp = angular.module("webApp", ['xml'])
        .config(function ($httpProvider) {
            $httpProvider.interceptors.push('xmlHttpInterceptor');
          })
        .controller("webCtrl", function($scope, $http) {
            $http.get("./data/web.json")
            .success(function(response) {
                $scope.websites = response;
                for (i = 0; i < $scope.websites.length; i++){
                    $http.get('../api/alexa?url=' + $scope.websites[i].url)
                    .success(function(rsp) {
                        //$scope.websites[i].rank = rsp.data.POPULARITY.TEXT;

                        console.log($scope.websites[i]);
                    });
                }
                console.log(response);
            });

        });
    </script>
Weijing Jay Lin
  • 2,991
  • 6
  • 33
  • 53

4 Answers4

1
.controller("webCtrl", function ($scope, $http) {
  $http.get("./data/web.json")
    .success(function (response) {
      $scope.websites = response;
      for (i = 0; i < $scope.websites.length; i++) {
        $scope.processWebsites($scope.websites[i], i);
      }

    });
  $scope.processWebsites = function (website, index) {
    $http.get('../api/alexa?url=' + website.url)
      .success(function (rsp) {
        console.log($scope.websites[index]);
      });
  }

});

Try this code. This will create a new execution context, thereby removing any unintentional side effects due to async execution.

Pranav Raj S
  • 86
  • 1
  • 2
  • 8
1

You want to access i variable but if your request taking to much time then for loop will not wait it will do ajax call and execute so after for loop end your i will be $scope.websites.length + 1 (because of i++) so you will get undefined to solve this problem you have to use closure function

JavaScript closure inside loops – simple practical example

var funcs = [];

function createfunc(i) {

    return function() {
        $http.get('../api/alexa?url=' + $scope.websites[i].url)
            .success(function(rsp) {
                //$scope.websites[i].rank = rsp.data.POPULARITY.TEXT;
                console.log($scope.websites[i]);
            });

    };
}
$http.get("./data/web.json")
    .success(function(response) {
        $scope.websites = response;
        for (i = 0; i < $scope.websites.length; i++) {
            funcs[i] = createfunc(i)
            $http.get('../api/alexa?url=' + $scope.websites[i].url)
                .success(function(rsp) {
                    //$scope.websites[i].rank = rsp.data.POPULARITY.TEXT;

                });
        }
        console.log(response);
    });
for (i = 0; i < funcs.length; i++) {

    funcs[i]();
}

Community
  • 1
  • 1
Keval Bhatt
  • 6,224
  • 2
  • 24
  • 40
0

I am not sure How your response json looks like but it should be array of key value pairs or a single key value pair so if you have like

[ {key:value},{key:value},{key:value}]

as response assuming a key is url in your case

it should directly work for you now you are asking for a key called i that is website[i] which is undefined.

try doing this

foreach loop

Dagm Fekadu
  • 598
  • 1
  • 8
  • 22
0

i isn't defined at your second success callback since it is an async callback and when it is been called the parent scope isn't valid anymore since it was executed without defining any local variables, you should define the iterator inside the for loop so it will be proper declared and hoisted

but you should be aware that since it is an async callback you will have a race condition when most of the chances that the loop will end before the first call back will be called and the iterator value in all of the iteration will be the array size (the last value)

var a = [1, 2, 4]


for (var i = 0; i < a.length; i++) {
  var that = this;
  that.iterator = i;
  setTimeout(function() {
    alert(a[that.iterator]);
  }, 10);


}

I would suggest you to aggregate the calls and use an aggregated callback to handle all of them together using $q.all

Itsik Avidan
  • 1,681
  • 1
  • 12
  • 7