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

当我运行上面的代码时,我从 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

4 回答 4

2

TypeError: $object.property is undefined通常是因为在设置特定对象(或其属性)之前发出了对对象引用的请求。$http请求本质上是异步的,因此其他进程不会被阻塞。很明显,尝试使请求同步可能会对连接速度非常慢的人造成重大问题。

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

说了这么多,在我看来,您似乎不想发出多个请求来检索相同的数据。如果是这样,您可以使用 $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 中使用命名空间的方法。

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

于 2015-08-10T14:42:09.130 回答
0

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

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

但是初始化仍在继续,因此您可能在 itemService 成功之前访问 $rootScope.items (或者它失败,并且您没有预测到这种情况)。我建议你这样做(如果你想遵循 $rootScope 约定..顺便说一句很糟糕):

 $rootScope.items = [];
 itemService.success(function(response){
    $rootScope.items = response;
 });
于 2015-08-10T13:09:02.450 回答
0

您正在设置items异步进程的回调,因此您试图items$rootScope实际设置之前访问。

如果您尝试在items加载控制器时进行初始化,那么还有其他方法可以做到这一点,例如使用路由的解析块或$http.get在控制器加载时手动调用工厂。

于 2015-08-10T13:10:06.193 回答
0

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

这实际上解决了我的问题。

于 2015-08-21T15:44:06.573 回答