问题描述
我有两项服务 - 一项用于存储用户详细信息,另一项用于调用以检索这些详细信息:
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:
小引用:
请记住,如果您的状态的视图是嵌套的,那么范围属性只会沿状态链向下继承.范围的继承属性与状态的嵌套和一切无关视图的嵌套(模板).
您完全有可能拥有嵌套状态,其模板在您站点内的各种非嵌套位置填充 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 内容传递到子状态 - 如果它们的视图是嵌套的.
例如,$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',},
},
在这里
这篇关于使用服务和控制器控制操作顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!