使用服务和控制器控制操作顺序

时间:2014-10-20 17:21:20

标签: angularjs angularjs-service angular-ui-router

我有两个服务 - 一个用于存储用户详细信息,另一个用于调用以检索这些详细信息:

userService存储要在整个应用程序中使用的用户详细信息(即注入控制器,服务等)

function userService($log) {        
    var id = '';
    var username = '';
    var isAuthenticated = false;

    var service = {
        id: id,            
        username: username,
        isAuthenticated: isAuthenticated
    };

    return service;
}

使用authService(希望只有一次)从Web API控制器检索用户详细信息:

function authService($log, $http, userService) {
    $log.info(serviceId + ': Inside authService method');

    var service = {
        getUserDetails: getUserDetails
    };

    return service;

    function getUserDetails() {
        $log.info(serviceId + ': Inside getUserDetails method');

        return $http.get('api/authentication', { cache: true });
    }
}

最初,我在.run块中调用了authService fire,如下所示:

.run(['$log', 'authService', 'userService', function ($log, authService, userService) {

    authService.getUserDetails()
        .then(querySucceeded);

    function querySucceeded(result) {
        userService.id = result.data.Id;
        userService.username = result.data.username;
    }
}]);

但问题是getUserDetails返回的promise在我的控制器被解雇之后才解决,因此对我来说太迟了。用户数据尚未就绪。

然后我查看了$ stateProvider中的resolve选项(对于UI-Router):

.state('dashboard', {
                url: '/dashboard',
                views: {
                    header: {
                        templateUrl: 'app/partials/dashboard/header.template.html',
                        controller: 'DashboardHeaderController',
                        controllerAs: 'dashboardHeaderVM',
                        resolve: {
                            user: function (authService) {
                                return authService.getUserDetails();
                            }
                        }
                    }
                }
            })

假设在解析部分中的promise得到解决后才会呈现视图。这似乎工作正常。

这是我使用返回的用户属性的控制器的(相关部分):

function DashboardHeaderController($log, user) {
    var vm = this;

    // Bindable members        
    vm.firstName = user.data.firstName;
}

但是,我有两条路线(更多来路),用户可以导航到其中一条路线。我是否需要在authService的每个州部分都有一个resolve属性?无论服务于哪条路由,我都要激活对authService.getUserDetails的调用,并在此之后为任何路由,控制器等提供它。

有更好的(最佳实践)方法吗?

2 个答案:

答案 0 :(得分:1)

不确定更好或最佳做法,但我的方式是plunker

重点是将resolve移动到某些根状态。申请中所有州的祖先:

$stateProvider
  .state('root', {
    abstract : true,
    // see controller def below
    controller : 'RootCtrl',
    // this is template, discussed below - very important
    template: '<div ui-view></div>',
    // resolve used only once, but for available for all child states
    resolve: {
      user: function (authService) {
          return authService.getUserDetails();
      }
    }
  }) 

这是解决的根状态。唯一有决心的国家。这是第一个孩子的例子(任何其他孩子都会以类似的方式定义:

$stateProvider
    .state('index', {
        url: '/',
        parent : 'root',
        ...

这种方法可以开箱即用。我只想提一下,如果'RootCtrl'定义如下:

.controller('RootCtrl', function($scope,user){
  $scope.user = user;
})

我们应该了解UI-Router继承。参见:

小引用:

  

请记住,只有嵌套状态的视图时,范围属性才会继承状态链。 范围继承属性没有嵌套状态所有嵌套您的观点(模板)。

     

完全有可能您有嵌套状态,其模板在您网站中的各种非嵌套位置填充ui-views。在这种情况下,您不能期望在子状态视图中访问父状态视图的范围变量...

可以在此Q & A

中找到更多解释

那么,这是什么意思?

  

我们的根视图只能将已解决的内容传递到子状态 - 如果它们的视图是嵌套的。

例如, $scope.user 只有在嵌套时才会在子状态/ views / $ scope中继承

.state('index', {
    url: '/',
    parent : 'root',
    views: { 
      '' : { // the root view and its scope is now the ancestor
             // so $scope.user is available in every child view
        templateUrl: 'layout.html',
        controller: 'IndexCtrl'
      },
      'top@index' : { templateUrl: 'tpl.top.html',},
      'left@index' : { templateUrl: 'tpl.left.html',},
      'main@index' : { templateUrl: 'tpl.main.html',},
    },

检查here

答案 1 :(得分:0)

如果我正确理解你想要在页面加载时,你会在任何控制器或服务请求之前获得用户信息。

我目前的项目中有类似的任务。

为了解决这个问题,我在app bootstapping&amp;之前手动请求了当前的用户信息。将其存储在localStorage

然后在app引导后,所有控制器/服务都可以访问当前用户信息。

提示:要在app bootstrap之前获取用户信息,您仍然可以通过手动注入来使用$ http服务:

angular.injector(['ng']).get('$http');