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>
2
  • 2
    for (var i = 0; i < $scope.websites.length; i++); try this Commented Dec 21, 2015 at 10:14
  • see my answer may be it will help you Commented Dec 21, 2015 at 10:59

4 Answers 4

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.

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

Comments

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]();
}

1 Comment

Great, you are right :) In this case, Pranav provide better answer, but your direction just right :)
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

Comments

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

2 Comments

what if it will take more time ?
it shouldn't be a difference on how much time it will take as long as you treat the callback as async and pass or declare the arguments

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.