2015-08-10 2 views
3

У меня есть некоторые параметры в $rootScope, как указано ниже:

myApp.factory('itemService', function($http) { 
    return $http.get('/items'); 
}); 

myApp.run(function($rootScope, itemService) { 
    itemService.success(function(response) { 
     $rootScope.items = response; 
    }); 
}); 

myApp.controller('displayCtrl', function($rootScope, $scope) { 
    $scope.items = $rootScope.items; 
}); 

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

Вот небольшое дополнение. items представляет собой массив со списком объектов, как это:

items = [ 
    {'name': 'spoon', 'price': 200}, 
    {'name': 'table', 'price': 400}, 
    {'name': 'shoe', 'price': 250} 
]; 

Я хотел бы сделать items доступны постоянно в моем приложении таким образом, что я могу отобразить каждый элемент в списке элементов (пункты), не делая еще один запрос к серверу , Я намереваюсь достичь этого, просто отображая элемент, используя $scope.item = items[$routeParams.id] каждый раз, когда мне нужно отображать элемент. Я с нетерпением жду этого, используя либо функцию, присоединенную к ng-click, либо обычный #/route/:param. Благодаря

+1

Я предполагаю, что itemService - это служба, которая содержит HTTP-вызовы для ресурсов и возвращает обещанный объект при вызове метода службы, поэтому где вызов? Не должно быть itemService.get(). Succes() и так далее. Кроме того, почему вы помещаете данные на rootScope? Таким образом, вы загрязняете rootScope. Вы можете полностью ввести itemService в displayController? – skubski

+0

Завод содержит '$ http.get()' while run() содержит '.success'. Также я помещаю данные в $ rootScope, потому что хочу, чтобы он был доступен, как только загрузится файл/приложение. –

+1

Плохо, я не видел заводского кода. (Я не думаю, что он был доступен, когда я прокомментировал). В этом случае вы запрашиваете ссылку на неопределенный (еще не установленный) объект, потому что http get все еще выполняется. В любом случае вы должны обновить свою фабрику и получить эти данные у rootScope, это плохая практика, и есть много документации, почему это так. – skubski

ответ

0

Наконец-то я смог придумать решение. Я понял, что проблема заключалась в том, чтобы $rootScope.items был доступен в displayCtrl одновременно с загрузкой. Но $rootScope.items доступен на мой взгляд, когда загружается моя страница html. Так что я просто передал пункт идентификатор в качестве параметра и получил его с помощью $routeParams следующим

myApp.controller('displayCtrl', function($routeParams, $scope) { 
    $scope.item_id = $routeParams.id; //given that the route looks like '/item/:id' 
}); 

Тогда в моем HTML-файл это то, что я сделал

<div ng-bind="items[item_id].name"></div> 
<div ng-bind="items[item_id].price"></div> 

Это действительное решить мою проблему.

+0

Тем не менее, это плохая практика. Вы должны использовать '$ rootScope' для хранения и обмена данными. -1 – skubski

+0

Спасибо, что выбрали это. Пожалуйста, направляйте меня на стандартный способ достижения этого без использования '$ rootScope', хранения и совместного использования данных. –

+0

Я уже ответил, что некоторое время назад! ;) – skubski

0

Вы запускаете asynchronious метод на этапе выполнения:

itemService.success(function(response){ 
    $rootScope.items = response; 
}); 

Но инициализация продолжается, так что, вероятно, вы получаете доступ $ rootScope.items до того itemService успеха (или это не удается, и, которого не прогнозируют такую ​​ситуацию). Я предлагаю вам сделать это (если вы хотите следовать за $ rootScope convension .. что плохо, кстати):

$rootScope.items = []; 
itemService.success(function(response){ 
    $rootScope.items = response; 
}); 
+0

Пожалуйста, вы можете уточнить меня с хорошим или лучшим способом сделать это. Лучшая практика - ключ к качественному коду. Я так ценю. –

0

Вы устанавливаете items в функции обратного вызова асинхронного процесса, так что вы пытаетесь получить доступ items на $rootScope перед его фактически установленным.

Если вы пытаетесь инициализировать items при загрузке контроллера, то есть другие способы сделать это, например, использовать блок разрешения маршрута или вручную вызвать $http.get на заводе при загрузке контроллера.

2

TypeError: $object.property is undefined обычно происходит потому, что запрос на ссылку объекта делается до того, как был установлен определенный объект (или его свойство). $http запросы являются асинхронными по своей природе, поэтому другие процессы не блокируются. Должно быть очевидно, что попытка синхронизировать запросы может вызвать серьезную проблему для людей с очень медленными соединениями.

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

Сказав все это, мне кажется, что вы не хотите делать несколько запросов для получения тех же данных. Если это так, вы можете использовать опцию cache для методов $ http.get.

например:

myApp.factory('itemService', function($http, $q) { 
    return { 
    get: function() { 
     return $http({ 
     url: 'items.json', 
     cache: true //keep the result in memory 
     }); 
    } 
    }; 
}) 

myApp.controller('aCtrl', function(itemService) { 
    var self = this; 

    itemService.get().success(function(data) { 
    self.items = data; 
    }); 
}); 

myApp.controller('bCtrl', function(itemService) { 
    var self = this; 

    itemService.get().success(function(data) { 
    self.items = data; 
    }); 
}); 

Это позволит убедиться, что информация получает запрашивается один раз и поместить в кэш. Данные доступны в разных местах.

<div ng-controller="aCtrl as a"> 
    {{a.items}} 
    </div> 
    <div ng-controller="bCtrl as b"> 
    {{b.items}} 
    </div> 

Это оставляет меня с другой «хорошей» практикой: использование синтаксиса controllerAs.Это дает возможность использовать пространства имен в AngularJS.

Конечно, это только советы, и вы всегда должны учитывать требования!

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

  • Нет связанных вопросов^_^