我无法在我的控制器中访问 $rootScope
I am unable to access $rootScope in my controller
我在 $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
机制来实现这一点。
谢谢
您 运行 在 运行 块的异步方法:
itemService.success(function(response){
$rootScope.items = response;
});
但是初始化还在继续,所以您可能在 itemService 成功之前访问了 $rootScope.items(或者它失败了,而您没有预料到这种情况)。我建议你这样做(如果你想遵循 $rootScope 约定......顺便说一句,这很糟糕):
$rootScope.items = [];
itemService.success(function(response){
$rootScope.items = response;
});
您正在异步进程的回调中设置 items
,因此您试图在 $rootScope
实际设置之前访问 items
。
如果您尝试在加载控制器时初始化 items
,那么还有其他方法可以做到这一点,例如使用路由的解析块或手动调用 $http.get
控制器加载时的工厂。
TypeError: $object.property is undefined
通常是因为在设置特定对象(或其 属性)之前发出了对对象引用的请求。 $http
请求本质上是异步的,因此其他进程不会被阻塞。很明显,尝试使请求同步可能会给连接速度非常慢的人带来重大问题。
除此之外,污染 $rootScope
通常不是一个好主意。您可以在下面的 link 上找到有关全局变量的主题,以便您调查为什么 $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>
这给我留下了另一个 'good' 实践:controllerAs 语法的用法。它提供了一种在 AngularJS 中使用命名空间的方法。
当然,这些只是提示,您应该始终考虑这些要求!
最后,我想出了一个解决办法。我意识到问题是 $rootScope.items
在 displayCtrl
加载的同时可用。但是当我的 html 页面加载时,$rootScope.items
在我的视图中可用。
所以我只是简单地将item 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>
这实际解决了我的问题。
我在 $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
机制来实现这一点。
谢谢
您 运行 在 运行 块的异步方法:
itemService.success(function(response){
$rootScope.items = response;
});
但是初始化还在继续,所以您可能在 itemService 成功之前访问了 $rootScope.items(或者它失败了,而您没有预料到这种情况)。我建议你这样做(如果你想遵循 $rootScope 约定......顺便说一句,这很糟糕):
$rootScope.items = [];
itemService.success(function(response){
$rootScope.items = response;
});
您正在异步进程的回调中设置 items
,因此您试图在 $rootScope
实际设置之前访问 items
。
如果您尝试在加载控制器时初始化 items
,那么还有其他方法可以做到这一点,例如使用路由的解析块或手动调用 $http.get
控制器加载时的工厂。
TypeError: $object.property is undefined
通常是因为在设置特定对象(或其 属性)之前发出了对对象引用的请求。 $http
请求本质上是异步的,因此其他进程不会被阻塞。很明显,尝试使请求同步可能会给连接速度非常慢的人带来重大问题。
除此之外,污染 $rootScope
通常不是一个好主意。您可以在下面的 link 上找到有关全局变量的主题,以便您调查为什么 $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>
这给我留下了另一个 'good' 实践:controllerAs 语法的用法。它提供了一种在 AngularJS 中使用命名空间的方法。
当然,这些只是提示,您应该始终考虑这些要求!
最后,我想出了一个解决办法。我意识到问题是 $rootScope.items
在 displayCtrl
加载的同时可用。但是当我的 html 页面加载时,$rootScope.items
在我的视图中可用。
所以我只是简单地将item 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>
这实际解决了我的问题。