【问题标题】:Ensuring one AngularJS controller loads before another确保一个 AngularJS 控制器在另一个之前加载
【发布时间】:2013-08-24 20:10:51
【问题描述】:

我会以这样一个事实作为开头,我真的不知道这是否是实现我正在做的事情的最佳方式,并且我非常愿意接受更好的建议。

我有一个使用OAUTH2 的用户帐户系统,它在我的数据库中查找用户信息并将其保存为变量$rootScope.userInfo。这驻留在附加到我的应用程序的body 的控制器中;在这里,我认为最高级别的控制器会先于其中的控制器加载,但显然不是。

如果我在我的mainCtrl 有机会从我的数据库中加载它之前加载一个尝试访问这个$rootScope.userInfo 对象的视图,它会引发一个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>

我正在像这样在mainCtrl 中加载$rootScope.userInfo

$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 没有时间加载,我会收到错误。

我该如何解决这个问题?

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    您描述的问题是不建议使用$rootScope 在控制器之间共享数据的原因之一:它会在两个控制器之间创建手动“不可见”依赖关系,当最终用户没有时您必须手动修复它'还没有通过另一个控制器。

    推荐的解决方案是将用户加载逻辑移动到服务中,例如userProfileService,您将其注入到需要它的两个控制器中。然后它将被创建一次,并用于两个控制器。在这样的服务中,您可以在控制器请求时使用$http 加载用户配置文件,并在下一个控制器请求时从缓存中返回它。这样,依赖关系从两个控制器传递到共享服务,而不是从一个控制器传递到另一个控制器。

    我不是 AngularJS 文档的忠实粉丝,但这些可能会有所帮助:DICreating ServicesInjecting Services

    【讨论】:

    • 这非常接近,我喜欢将其用作服务的想法。但是它并不能解决加载顺序问题。我已经设置了服务,但它仍然会在服务返回任何数据之前加载控制器!想法?
    • 我在这里提出了一个更新的问题:stackoverflow.com/questions/18477711/… 我会接受这个作为答案,因为它完成了大部分工作,但也可以随意回答。
    【解决方案2】:

    使用then代替success并使用ng-include延迟加载子控制器:

    <body ng-controller="mainCtrl">
        <header>Content</header>
        <ng-include src="templatePath"></ng-include>        
    </body>
    

    将 HTML 移入新模板 userprofile.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";
        });
    

    【讨论】:

    • $http.success(foo)$http.then(foo) 的别名,可以正确传递所有参数。将success 更改为then 会解决什么问题?见the source
    • @stevuu 是的。似乎没有必要使用其中一个。
    猜你喜欢
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多