使用服务和控制器控制操作顺序 [英] Controlling order of operations with services and controllers

查看:29
本文介绍了使用服务和控制器控制操作顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two services - one to store user details and the other to make a call to retrieve those details:

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,如下所示:

Initially, I had the call to the authService fire in a .run block like so:

.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 返回的承诺直到我的控制器触发后才解决,因此对我来说为时已晚.用户数据未准备好.

But the problem was that the getUserDetails-returned promise did not resolve until after I my controllers fired and, thus, too late for me. The user data was not ready.

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

I then looked at the resolve option in the $stateProvider (for 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();
                            }
                        }
                    }
                }
            })

假设在 resolve 部分中的 promise 被解决之前,视图不会被呈现.这似乎工作正常.

The assumption is that the view won't be rendered until the promise in the resolve section is, well, resolved. That seems to work fine.

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

Here's the (relevant part of the) controller where I use the returned user property:

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

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

但是,我有两条路线(更多路线),用户可以导航到任一路线.我是否需要在 authService 的每个状态部分都有一个解析属性?我想调用 authService.getUserDetails 一次,无论提供哪个路由,然后让它可用于任何路由、控制器等.

However, I have two routes (more to come) and a user can navigate to either one. Do I need to have a resolve property in each state section for the authService? I want to fire the call to authService.getUserDetails just once no matter which route is served and have it available after that for any route, controller, etc.

有没有更好的(最佳实践)方法来做到这一点?

Is there a better (best practice) way to do this?

推荐答案

不确定更好或最佳实践,但这里有一个 plunker 以我的方式.

Not sure about better or best practice, but here is a plunker with my way.

重点是将resolve 移动到某个 根状态.应用程序中所有状态的祖先:

The point is to move resolve into some parent root state. The one who is ancestor of all states in the application:

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

这是具有resolve的根状态.唯一有决心的国家.这是它的第一个孩子的示例(任何其他孩子都将以类似方式定义:

This is a root state with resolve. The only state with resolve. Here is an example of its first child (any other would be defined similar way:

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

这种方法开箱即用.我只想提一下,如果 'RootCtrl' 是这样定义的:

This approach will work out of the box. I just would like to mention that if the 'RootCtrl' is defined like this:

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

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

we should understand the UI-Router inheritance. See:

小引用:

请记住,如果您的状态的视图是嵌套的,那么范围属性只会沿状态链向下继承.范围的继承属性状态的嵌套一切无关视图的嵌套(模板).

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).

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

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states...

更多解释可以在这个Q &一个

那么,这是什么意思?

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

Our root view can pass the resolved stuff into child state only - if their views are nested.

例如,$scope.user 只会在子状态/视图/$scopes 像这样嵌套时才会被继承

For example, the $scope.user will be inherited in child states/views/$scopes only if they are nested like this

.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',},
    },

这里

这篇关于使用服务和控制器控制操作顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆