情况是,我在(运行(有"routeChangeSuccess">事件。该事件根据 REST 请求响应状态代码更改 $rootScope.已验证的值。
但是,当触发事件并且我尝试将其中一个控制器中的 $rootScope.authenticated 值打印到控制台时,它说它是"未定义"的值。
角度运行:
pos.run(function($rootScope,$log,apiService){
// register event
$rootScope.$on('$routeChangeSuccess', function () {
// call api function
apiService.is_authenticated().then(
function(response){
if(response.status == "AUTHENTICATED"){
$rootScope.authenticated = true;
}else if(response.status == "NOT_AUTHENTICATED"){
$rootScope.authenticated = false;
}
});
})
});
控制器:
// controller
pos.controller('TestController', function($rootScope,$scope,$http) {
console.log($rootScope.authenticated);
});
它应该打印"真"或"假"。我知道它在执行控件后分配值,但是如何延迟执行控制器直到分配该值?
事实是,如果您使用$promise模式,则永远无法保证执行顺序,因为它是异步的,或者具有足够"安全"的延迟。
您可能想在其他地方进行更改,一种方法是使其同步:
if (apiService.is_authenticated()){
$rootScope.authenticated = true;
}
另一种是$broadcast或$emit,也许在"运行"中再次收听
$rootScope.$on("LOGIN_SUCCESSFUL", function () {
$rootScope.authenticated = true;
});
您可以合并$watch
或使用 http 拦截器
或更多承诺和/或链接承诺
很多方法,但这取决于你!
最近研究了相同的解决方案,并在SO上阅读了很多答案。实际上有很多东西要找,但没有一个被接受的答案实际上对我有用。我找到了一个适用于最新ui路由器的答案,但不接受:
它调用 stateChangeStart 事件上的 preventDefault,然后你可以履行你的承诺。 如果成功,则设置一个绕过标志,并再次转换到相同的状态,但由于绕过标志而跳过承诺/解析部分:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
if($rootScope.stateChangeBypass || toState.name === 'login') {
$rootScope.stateChangeBypass = false;
return;
}
event.preventDefault();
Auth.getCurrentUser().then(function(user) {
if (user) {
$rootScope.stateChangeBypass = true;
$state.go(toState, toParams);
} else {
$state.go('login');
}
});
});
取自: https://stackoverflow.com/a/28827077/2019281
我目前正在研究的另一个选项是使用根状态定义的解析对象。Resolve非常适合这一点,因为它将阻止控制器初始化,直到承诺被解析或拒绝。您可以在拒绝时抛出错误,您可以在应用程序的运行方法中捕获该错误:
状态定义:
$stateProvider.state('admin', {
'url': '/admin',
'controller': 'adminController',
'templateUrl': 'admin.html'
'resolve': {
'auth': [
'$q', 'Auth',
function ($q, Auth) {
return Auth.getCurrentUser().then(
function resolved (user) {
return (user) ? user : $q.reject('authRejected');
},
function rejected (user) {
return $q.reject('authRejected');
}
});
}
]
}
});
应用的运行方法:
$rootScope.$on('$stateChangeError', function (e, toState, toParams, fromState, fromParams, error) {
if (error === 'authRejected') {
$state.go('login');
}
});
缺点是您需要将根状态添加到要保护的状态,或者将该解析添加到要保护的每个状态。此外,您始终需要在状态更改上使用reload: true
,以便解析将在每次状态更改时重新加载。
灵感来源:https://stackoverflow.com/a/24585005/2019281