【发布时间】:2015-10-28 23:03:03
【问题描述】:
我知道通常你不想这样做,但我发现了一个用例,我似乎找不到任何其他解决方案,并希望我的函数包含一个承诺等到承诺解决在返回任何东西之前。
我正在修改应用程序的身份验证机制,并设置了以下代码,以在 $state 更改时仔细检查用户是否已获得授权,如果未授权,则将其重定向回登录屏幕:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
// double check that the user is logged in
if (toState && toState.name.indexOf('auth')<0) {
if (!user.isAuthorized()) {
event.preventDefault(); // do not continue to the non-auth state
user.logout();
$state.go("auth.login");
}
}
});
目前,user.isAuthorized() 函数只是从用户登录或注销时设置/取消设置的内部布尔值返回真或假值,一切正常。
但是,我们需要将该函数调用到服务器(如果本地布尔值设置为 false)以检查用户是否已经有活动会话,然后设置布尔值并返回 true。在服务器调用返回之前,我们不希望应用程序执行任何操作,因为它正在检查用户是否应该能够看到 UI。
我曾尝试使用 Promise 来处理这种情况,但它产生了意想不到的结果,因为 event.preventDefault() 调用不会立即被调用(仅在 Promise 解决后),此时 $state 已经改变了。至少这会导致 UI 在发送到登录屏幕之前短暂闪烁,并且在某些情况下,其他 $states 在加载时会进行自己的服务器调用,这会失败和/或导致浏览器提示用户进行基本授权(用户名/密码)。
这不起作用:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
// double check that the user is logged in
if (toState && toState.name.indexOf('auth')<0) {
user.isAuthorized().then(function(isAuthorized) {
if (!isAuthorized()) {
event.preventDefault(); // this does not prevent state change any more
user.logout();
$state.go("auth.login");
}
});
}
});
我认为我们需要让 user.isAuthorized() 函数看起来像这样:
user.isAuthorized = function() {
if(user.isAuthorizedBoolean) {
return true;
} else {
var returnValue = false;
// make server side call that returns promise
user.isAuthorizedServerCheck().then(function(result) {
if (result === true) {
returnValue = true;
}
});
// pause execution until promise resolves???
return returnValue;
}
};
但我不知道如何做到这一点。
【问题讨论】:
-
这个的解决方案(不是sync - 而是这个问题的解决方案)可以在这里找到stackoverflow.com/a/26702638/1679310
-
不是你不想想要这样做,而是你不能这样做。
-
让你的方法总是返回一个被解析为真或假的承诺。
-
@RadimKöhler - 我想这正是我想要的,谢谢!
-
@BrianMedendorp 很高兴看到这一点!享受强大的 UI-Router ;)
标签: angularjs angular-ui-router promise