Почему $http.get() не определен в моем сервисе Angular?

Я пытаюсь загрузить некоторый JSON и сохранить его с помощью $rootScope, чтобы он сохранялся между контроллерами. Когда я запускаю свое приложение, я получаю следующую ошибку:

TypeError: Cannot call method 'get' of undefined

Метод get работал отлично, пока я не попытался ввести $rootScope... есть идеи?

Мой сервис выглядит так:

  1 /**
  2  * Service to get the quiz data from a JSON source
  3  */
  4 app.factory('quizService', ['$rootScope', function ($scope, $rootScope, $http) {
  5     var promise;
  6     var service = {
  7         getQuiz: function($scope, $http) {
  8             if ( !promise ) {
  9                 promise = $http.get('QuizFileName.quiz').then(function (response) {
 10                     return response.data;
 11                 });
 12             }
 13             return promise;
 14         }
 15     };
 16     return service;
 17 }]);

Мой контроллер выглядит так:

  7     // Get Quiz data from service
  8     quizService.getQuiz().then(function(data) {
  9         $scope.quiz = data;
 10
 11         // Redirect to scores if already completed this
 12         if($scope.quiz.complete === true) {
 13             $location.path('scores');
 14         }
 15     });

person Pete Thorne    schedule 13.03.2014    source источник


Ответы (3)


Вы используете «шаблон массива» при определении своей фабрики. У вас должна быть строка для каждой службы, которую вы используете в своей функции, но у вас есть только одна.

То есть то, что вы делаете,

app.factory('quizService', ['$rootScope', function ($scope, $rootScope, $http) {
    //insert code
}]);

но то, что вы должны сделать, это

app.factory('quizService', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) {
    //insert code
}]);

AngularJS сопоставит функции, названные строками, с параметрами. Попробуйте это и посмотрите, решит ли это вашу проблему.

EDIT: Ах, ответ от Reboog711 имеет больше смысла в решении проблемы, я почему-то пропустил последнюю часть кода. Но я оставляю этот ответ, так как вы также должны исправить фабричное определение.

person Axel Örn Sigurðsson    schedule 13.03.2014
comment
+! для выявления проблемы с проблемой обозначения массива. - person JeffryHouser; 13.03.2014
comment
Спасибо. Есть ли альтернатива шаблону массива для определения фабрик? - person Pete Thorne; 13.03.2014
comment
Я лично использую этот шаблон каждый раз, когда пишу угловой код, поскольку он предназначен для минимизации. Я бы лично рекомендовал вам продолжать использовать его. Происходит то, что после минимизации вы можете получить app.factory('quizService', ['$http', function (a) { .. }]);, поскольку минимизация уменьшит переменные до минимально возможного количества символов. Строки не изменяются, поэтому angular проверяет первую строку и знает, что переменная a на самом деле равна $http. - person Axel Örn Sigurðsson; 13.03.2014

getQuiz — это функция внутри фабрики:

getQuiz: function($scope, $http) {

Когда вы вызываете getQuiz, вы не передаете ему никаких аргументов:

quizService.getQuiz()

$http не определен, потому что вы вызываете его без передачи каких-либо аргументов. Angular не будет внедрять элементы в функцию, которую вы вызываете вручную. Это будет делаться только с функциями, которые AngularJS вызывает сам, такими как функции контроллера или фабрики.

Итак, у вас есть несколько вариантов. Один из них — передать аргументы $scope и $http в функцию, например:

quizService.getQuiz($scope, $http)

Я уверен, что это решит проблему, но это наверняка будет странный подход.

Я бы, вероятно, удалил функции $scope и $http из определения функции:

 getQuiz: function() {

Затем убедитесь, что вы изменили определение фабрики:

app.factory('quizService', ['$scope','$rootScope','$http', function ($scope, $rootScope, $http) {

Без этой модификации службы Angular не будут переданы в вашу функцию.

Затем, когда вы обращаетесь к $http внутри функции, она должна обращаться к значению, переданному в фабрику, которое не должно быть неопределенным.

person JeffryHouser    schedule 13.03.2014
comment
Я так злюсь на себя за то, что пропустил это! Вы правы, мне нужно было добавить $http в определение. - person Pete Thorne; 13.03.2014

Хорошо, Reboog711 поставил меня на правильный путь, мне нужно было изменить определение фабрики, чтобы включить $http, я ранее пытался сделать это, но по ошибке собрал это так:

'$rootScope, $http'

Не делай этого, это плохо и неправильно! Но ответ Reboog711 также дал мне ошибки, потому что я думаю, что вы не можете использовать $scope так, как мы оба думали.

Правильным (или рабочим) решением было:

app.factory('quizService', ['$rootScope', '$http', function ($rootScope, $http) {

Я надеюсь, что это поможет другим новичкам в Angular. Большое спасибо всем, кто ответил своими комментариями. Я очень уважаю это сообщество за его отличное отношение к помощи другим :)

person Pete Thorne    schedule 13.03.2014