情况是,我在(运行)处有“routeChangeSuccess”事件。该事件根据REST请求响应状态代码更改 $ rootScope.authenticated 的值。
但是当事件被触发并且我尝试在我的一个控制器中向控制台打印 $ 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);
});
它应该打印“true”或“false”。我知道它在控制执行后分配值,但是如何延迟执行控制器直到分配该值?
答案 0 :(得分:2)
事实是,如果你使用$ promise模式,你永远不能保证执行顺序,因为它是异步的,或者具有足够“安全”的延迟。
您可能想要在其他地方进行更改,一种方法是使其同步:
if (apiService.is_authenticated()){
$rootScope.authenticated = true;
}
另一个是拥有$broadcast or $emit并在“再次”运行中听取它
$rootScope.$on("LOGIN_SUCCESSFUL", function () {
$rootScope.authenticated = true;
});
您可以合并到$watch
或more promises and/or chaining promises
很多方面,但这取决于你!
答案 1 :(得分:1)
最近在同一个解决方案上工作并在此处阅读了大量答案。实际上有很多东西要找,但是没有一个可接受的答案对我有用。我找到了一个适用于最新ui-router的答案,但它并没有被接受:
它在stateChangeStart事件上调用preventDefault,然后你可以满足你的承诺。如果成功则设置旁路标志并再次转换到相同的状态,但由于旁路标志而跳过promise / resolve部分:
$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对象。 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');
}
});
}
]
}
});
App的运行方法:
$rootScope.$on('$stateChangeError', function (e, toState, toParams, fromState, fromParams, error) {
if (error === 'authRejected') {
$state.go('login');
}
});
缺点是,您需要将根状态添加到要保护的状态,或将该解析添加到要保护的每个状态。此外,您始终需要在状态更改上使用reload: true
,以便在每个状态更改时重新加载解析。