2015-08-18 4 views
1

Немного нова для Angular и javascript. У меня есть следующий контроллер, который использует фабричную службу для доступа к локальному файлу JSON. Большая часть этого кода получается (или полностью взята) от this post by Dan Wahlin. Я не могу получить доступ к переменной $ scope.books вне функции и не могу понять, почему. Консоль.log внутри функции дает мне объект, который я ищу, но один внешний возвращает undefined. Что я здесь делаю неправильно? Благодарю.

app.controller('FormController', ['$scope', 'tocFactory', function ($scope, tocFactory) { 

    $scope.books; 

    getBooks(); 

     function getBooks() { 
     tocFactory.getBooks(). 
      success(function(data, status, headers, config) { 
      $scope.books = data; 
      console.log($scope.books); 
      }). 
      error(function(data, status, headers, config) { 
      // log error 
    }) 
    } 
    console.log($scope.books); 
    }]); 
+1

Все в порядке, console.log внутри 'success' возвращает правильный объект. Добро пожаловать в мир асинхронных методов. –

+0

Я думаю, это зависит от вашего определения OK. Я не могу привязываться к нему в своем HTML или использовать его в других частях моего контроллера в его текущей форме. Как я могу сделать это так, чтобы я мог? – GMarsh

+0

Весь смысл привязки данных для пользовательского интерфейса заключается в том, что всякий раз, когда ваши данные изменяются, пользовательский интерфейс автоматически отражает это. Ваши привязки не должны быть прав. –

ответ

3

Потому что вы делаете ajax и затем выполняете следующую строку кода. Это не значит, что у вас есть гарантия, что ваш ответ ajax готов к выполнению следующей строки кода.

Вы всегда можете получить его значение отклика внутри функции успеха $http, которая вызывается при успешном выполнении ajax-вызова.

Читать здесь How asynchronous call works?

2

на самом деле это не проблема масштаба, но сроки. Функция getBooks выполняется асинхронно, поэтому при возникновении вашего консольного журнала это, скорее всего, не будет связано ни с чем. Вы можете проверить это легко с интервалом, чтобы увидеть, как это происходит:

app.controller('FormController', ['$scope', 'tocFactory', function($scope, tocFactory) { 
    $scope.books; 
    getBooks(); 
    function getBooks() { 
    tocFactory.getBooks() 
     .success(function(data, status, headers, config) { 
     $scope.books = data; 
     console.log($scope.books); 
     }) 
     .error(function(data, status, headers, config) { 
     // log error 
     }) 
    } 
    setInterval(function(){ 
    console.log($scope.books); 
    }, 1000); 
}]); 
+0

Что делать, если ответ займет больше 1 секунды? –

+1

мой быстрый демо-код предлагает играть с setInterval, а не setTimeout. Он будет просто повторять ведение журнала каждые 1 секунду навсегда, поэтому, скорее всего, он выйдет из 'undefined' один или несколько раз, а затем выдает некоторое значение после того, как .success называется – wesww

+0

Thats my bad..I неправильно прочитал, что .. –

0

Вы можете использовать $ Q сервис для обработки асинхронного кода с обещаниями:

app.controller('FormController', ['$scope', '$q', 'tocFactory', function ($scope, $q, tocFactory) 
{ 

    var getBooks = function() 
    { 
     var deferred = $q.defer(); 

     tocFactory.getBooks(). 
     success(function(data, status, headers, config) 
     { 
      $scope.books = data; 
      deferred.resolve(); 
     }). 
     error(function(data, status, headers, config) 
     { 
      deferred.reject(); 
     }); 

     return deferred.promise; 
    }; 

    getBooks().then(function(res) 
    { 
     console.log($scope.books); // success : your data 
    }, function(res) 
    { 
     console.log($scope.books); // error : undefined 
    }); 

    console.log($scope.books); // undefined 

} ]); 

Я не проверял этот код, но он должен работать и показывать вам принцип обещаний. Подробнее о сервисе $ q: https://docs.angularjs.org/api/ng/service/ $ q

+1

Нет необходимости использовать '$ q', поскольку' $ http' уже возвращает обещание. Еще больше - методы успеха и ошибок теперь устарели - https://docs.angularjs.org/api/ng/service/$http - Утилиты $ http legacy обещают успех и ошибки, которые устарели. Вместо этого используйте стандартный метод. Если для параметра $ httpProvider.useLegacyPromiseExtensions установлено значение false, то эти методы будут вызывать ошибку $ http/legacy. –

Смежные вопросы