我无法在我的控制器中访问$ rootScope

时间:2015-08-10 13:00:40

标签: angularjs angularjs-scope angularjs-rootscope

我在$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;
});

当我运行上面的代码时,我从firebug得到了这个错误 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机制来实现此功能。 感谢

4 个答案:

答案 0 :(得分:2)

TypeError: $object.property is undefined通常是因为在设置了特定对象(或其属性)之前对对象的引用进行了请求。 $http请求本质上是异步的,因此其他进程不会被阻止。显而易见的是,尝试使请求同步可能会给连接速度很慢的人带来严重问题。

除此之外,污染$rootScope通常是一个坏主意。您可以在以下link上找到有关全局变量的主题,以便您调查$ rootScope不是一个好地方的原因。

说了这么多,在我看来,你并不想要多次请求来检索相同的数据。如果是这样,您可以使用$ http.get方法的缓存选项。

e.g:

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>

这让我有另一个好的&#39;练习:使用controllerAs语法。这提供了一种在AngularJS中使用命名空间的方法。

当然,这些只是提示,你应该始终考虑要求!

答案 1 :(得分:0)

您在运行块中运行异步方法:

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

但是初始化仍然存在,所以可能在itemService成功之前访问$ rootScope.items(或者它失败了,你没有预测到这种情况)。我建议你这样做(如果你想跟随$ rootScope召集......顺便说一下这很糟糕):

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

答案 2 :(得分:0)

您正在异步流程的回调中设置items,因此您在实际设置之前尝试访问items上的$rootScope

如果您在加载控制器时尝试初始化items,则还有其他方法可以执行此操作,例如使用路径的解析块或在工厂时手动调用$http.get控制器加载。

答案 3 :(得分:0)

最后,我能够提出一个解决方案。我意识到问题是$rootScope.items在加载的同时displayCtrl可用。但是当我的html页面加载时,我的视图中可以使用$rootScope.items。 所以我只是将项目ID作为参数传递,并使用$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>

这实际解决了我的问题。