Передающий массив не изменяется с помощью службы $http Angular

Я изучаю Angular, но застрял, пытаясь использовать службу $http и массив JSON. У меня есть массив с именем names. Я могу показать его содержимое внутри функции, но снаружи она показывает эту ошибку: TypeError: Cannot read property 'Name' of undefined. Я думаю, что массив не модифицируется должным образом. Но я не знаю почему. Я взял свой код из примера с W3shools.com (http://www.w3schools.com/angular/tryit.asp?filename=try_ng_customers_json). Я немного модифицировал его. Почему, когда я хочу показать содержимое переменной name во второй раз, я получаю сообщение об ошибке?

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);

person Roby Sottini    schedule 08.07.2015    source источник
comment
console.log за пределами $http.get().success(); вызывается перед console.log внутри $http.get().success(); завершено.   -  person C1pher    schedule 09.07.2015


Ответы (4)


$http.get() — это асинхронная служба. Попробуйте этот фрагмент вместо проверки изменений в модели:

$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);
});
person vorillaz    schedule 08.07.2015

При работе с JavaScript и асинхронными методами важно помнить, что разные части вашего кода будут выполняться в разные промежутки времени. Этот второй оператор console.log имеет отступ, но на самом деле этого не должно быть. Он находится на том же уровне, что и метод $http.get().

Что происходит в вашем коде, так это то, что выполняется вызов get, а затем JavaScript немедленно переходит к следующей строке (последний console.log) и выполняет ее, не дожидаясь ответа от метода get. Оператор console ссылается на массив имен, который все еще пуст от исходного экземпляра, и пытается сослаться на позицию индекса [0] и свойство .Name, которые еще не были установлены. На самом деле массив не будет заполнен в течение нескольких миллисекунд.

Вот схема действий в разбивке:

  1. Массив имен объявлен и создан пустым
  2. Вызывается метод $http.get()
  3. console.log массива имен (все еще пустой)
  4. Через некоторое время $http.get() возвращает ответ, запуская метод успеха
  5. Если ответ успешен, массив имен обновляется записями ответа.
  6. console.log массива имен (теперь с ответными записями)

И выполнение кода:

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);

person Daniel Nalbach    schedule 08.07.2015
comment
Вы объяснили проблему, но так и не предоставили решение, хотя я добавил +1. - person defau1t; 09.07.2015
comment
Оригинальный плакат на самом деле не просил решения, он спросил, почему. Я объяснил почему. По моему мнению, которое может быть ошибочным, смысл вопроса заключался в том, чтобы понять, почему один оператор console.log получил результат, а другой нет, что требует понимания асинхронного выполнения. Спасибо за +1. - person Daniel Nalbach; 09.07.2015

Вот как работает асинхронный код. Когда этот код запускается впервые, names равно []. $http.get запускает асинхронный запрос к "www.w3schools.com" и помещает success в цикл обработки событий. Тогда console.log("And now the name again: " + names[0].Name); запустится, а names останется [], потому что success еще не запустилось. Вот почему у вас есть ошибка. После завершения $http.get будет вызван success, и теперь names имеет значение, и команда log будет работать, как ожидалось.

person arb    schedule 08.07.2015

Служба angular $http.get является асинхронной. Это означает, что функция возвращается до вызова .success.

person Will    schedule 08.07.2015