0

I am learning Angular but I am stuck trying to use the $http service and a JSON array. I have an array called names. I can show its content inside the function, but outside it shows this error: TypeError: Cannot read property 'Name' of undefined. I think the array is not beeing modified properly. But I don't know why. I took my code from an example from W3shools.com (http://www.w3schools.com/angular/tryit.asp?filename=try_ng_customers_json). I modified it a little bit. Why when I want to show the content of the name variable the second time I get the error?

var names = [];
$http.get("http://www.w3schools.com/angular/customers.php")
    .success(function(response) {
        names = response.records;
        console.log("The name is: " + names[0].Name);
    });
    console.log("And now the name again: " + names[0].Name);
1
  • 1
    The console.log outside of the $http.get().success(); is getting called before the console.log inside of the $http.get().success(); is completed. Commented Jul 8, 2015 at 22:32

4 Answers 4

2

$http.get() is an asynchronous service . Try this snippet instead checking for a change on a model:

$scope.name = [];
$http.get("http://www.w3schools.com/angular/customers.php")
    .success(function (response) {
    $scope.name = response.records;
    console.log("The name is: " + $scope.name[0].Name);
});
$scope.$watchCollection('name', function (newNames, oldNames) {
    if (newNames.length > 0) console.log("The name is: " + $scope.name[0].Name);
});
Sign up to request clarification or add additional context in comments.

Comments

2

It's important to remember with JavaScript and asynchronous methods that different pieces of your code will be executing in different time-frames. That second console.log statement is indented but really shouldn't be. It is at the same level as the $http.get() method.

What happens in your code is that the get call is made and then JavaScript immediately moves to the next line (the last console.log) and executes it without waiting for the response from the get method. The console statement references the names array, which is still empty from the original instantiation, and tries to reference an index position [0] and property .Name that haven't been set yet. In reality, the array won't be populated for a few milliseconds.

Here's the activity flow broken down:

  1. names array is declared and instantiated empty
  2. $http.get() method is invoked
  3. console.log of names array (still empty)
  4. A short time later $http.get() returns a response, triggering the success method
  5. If the response is successful, the names array is updated with the response records
  6. console.log of names array (now with response records)

And the code execution:

1) var names = [];

2) $http.get("http://www.w3schools.com/angular/customers.php")

4) .success(function(response) {

    5)  names = response.records;
    6)  console.log("The name is: " + names[0].Name);

});

3) console.log("And now the name again: " + names[0].Name);

2 Comments

You explained the problem but never provided a Solution, i added +1 though.
The original poster actually didn't ask for a solution, he asked "why". I explained "why". In my judgement, which could be wrong, the point of the question was to understand why one console.log statement got a result and the other didn't, which requires an understanding of asynchronous execution. Thank you for the +1.
2

This is how asynchronous code works. When this code first runs, names is []. $http.get starts an asynchronous request to "www.w3schools.com" and puts success into the event loop. Then console.log("And now the name again: " + names[0].Name); will run and names is still [] because success hasn't run yet. That is why you have an error. Once $http.get completes, success will be called and now names has a value and the log command will work as expected.

Comments

1

The angular service $http.get is asynchronous. This means the function returns before .success is called.

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.