我将在此之前提到这样一个事实:我真的不知道这是否是实现我正在做的事情的最佳方式,而且我对更好的建议持开放态度。
我有一个使用OAUTH2
的用户帐户系统,它会在我的数据库中查找用户信息并将其另存为变量$rootScope.userInfo
。这位于我的应用程序body
附加的控制器中;在这里,我认为最高级别的控制器会在其中存在之前加载,但显然不是。
如果我在$rootScope.userInfo
有机会从我的数据库加载此对象之前加载了一个试图访问此mainCtrl
对象的视图,则会引发javascript错误并导致Angular
中断。
供参考,以下是模板的概念:
<body ng-controller="mainCtrl">
<header>Content</header>
<div class='main-view' ng-controller="userProfile">
<p>{{user.name}}</p>
<p>{{user.email}}</p>
</div>
</body>
我正在$rootScope.userInfo
加载mainCtrl
,如下所示:
$http.get('/api/users/' + $cookies.id).
success(function(data) {
$rootScope.userInfo = data.user[0];
console.log("User info is:");
console.log($rootScope.userInfo);
$scope.status = 'ready';
});
然后,对于我的userProfile
控件,我这样做:
function userProfile($scope, $cookies, $http, $routeParams, $rootScope){
if($scope.status == 'ready'){
$scope.user = $rootScope.userInfo;
console.log("Double checking user info, here it is:");
console.log($rootScope.userInfo);
}
}
如果我来自应用中不同于$rootScope.userInfo
的其他页面,则API有足够的时间查找,我的userProfile
页面正常工作。但是,如果进行整页刷新,则$rootScope.userInfo
没有时间加载,我会收到错误。
我该如何解决这个问题?
答案 0 :(得分:14)
您描述的问题是不建议使用$rootScope
在控制器之间共享数据的原因之一:它在两个控制器之间创建手动“不可见”依赖关系,您必须在结束时手动修复用户尚未通过其他控制器。
推荐的解决方案是将用户加载逻辑移动到服务中,例如userProfileService
,您将其注入需要它的两个控制器中。然后它将被创建一次,并用于两个控制器。在这样的服务中,您可以在控制器请求时使用$http
加载用户配置文件,并在下一个操作时从缓存中返回它。这样,依赖关系从两个控制器转到共享服务,而不是从一个控制器转到另一个控制器。
我不是AngularJS文档的忠实粉丝,但这些可能有所帮助:DI,Creating Services和Injecting Services。
答案 1 :(得分:0)
使用then
代替成功并使用ng-include
延迟加载子控制器:
<body ng-controller="mainCtrl">
<header>Content</header>
<ng-include src="templatePath"></ng-include>
</body>
在新模板userprofile.html
中移动HTML:
<div class='main-view' ng-controller="userProfile">
<p>{{user.name}}</p>
<p>{{user.email}}</p>
</div>
在mainCtrl中回调:
$http.get('/api/users/' + $cookies.id).
then(function(data) {
/* mainCtrl being the parent controller, simply exposing the
properties to $scope would make them available
to all the child controllers.*/
$rootScope.userInfo = data.user[0];
/* assign the template path to load the template and
instantiate the controller */
$scope.templatePath = "userprofile.html";
});