我想防止发生 Rails 设计超时时发生的一些闪烁,但 Angular 直到资源出现下一个授权错误时才知道。
发生的情况是模板被渲染,一些ajax调用资源发生,然后我们被重定向到rails设备进行登录。我宁愿在每次状态更改时对 Rails 执行 ping 操作,如果 Rails session 已过期,那么我将在渲染模板之前立即重定向。
ui-router 具有可以放在每个路由上的解析,但这看起来一点也不干。
我有的是这个。但只有在状态发生转变之前,这一 promise 才得以实现。
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
//check that user is logged in
$http.get('/api/ping').success(function(data){
if (data.signed_in) {
$scope.signedIn = true;
} else {
window.location.href = '/rails/devise/login_path'
}
})
});
在呈现新模板之前,如何根据 promise 的结果中断状态转换?
请您参考如下方法:
我知道这对于游戏来说已经太晚了,但我想发表我的意见并讨论我认为“暂停”状态更改的绝佳方法。根据 angular-ui-router 的文档,状态的“解析”对象的任何成员(作为 promise )必须在状态完成加载之前解析。所以我的功能(尽管尚未清理和完善)解决方案是在“$stateChangeStart”上向“toState”的解析对象添加一个 promise :
例如:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
toState.resolve.promise = [
'$q',
function($q) {
var defer = $q.defer();
$http.makeSomeAPICallOrWhatever().then(function (resp) {
if(resp = thisOrThat) {
doSomeThingsHere();
defer.resolve();
} else {
doOtherThingsHere();
defer.resolve();
}
});
return defer.promise;
}
]
});
这将确保状态更改适用于要解决的 promise ,这是在 API 调用完成并且基于 API 返回做出所有决策时完成的。在允许导航到新页面之前,我使用它来检查服务器端的登录状态。当 API 调用解析时,我要么使用“event.preventDefault()”停止原始导航,然后路由到登录页面(用 if state.name != "login"包围整个代码块),或者允许用户通过简单地解决延迟的 promise 来继续,而不是尝试使用旁路 bool 值和 PreventDefault()。
虽然我确信原始发帖者早已解决了他们的问题,但我真的希望这对其他人有帮助。
编辑
我想我不想误导人们。如果您不确定您的状态是否有解析对象,则代码应如下所示:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
if (!toState.resolve) { toState.resolve = {} };
toState.resolve.pauseStateChange = [
'$q',
function($q) {
var defer = $q.defer();
$http.makeSomeAPICallOrWhatever().then(function (resp) {
if(resp = thisOrThat) {
doSomeThingsHere();
defer.resolve();
} else {
doOtherThingsHere();
defer.resolve();
}
});
return defer.promise;
}
]
});
编辑2
为了使其适用于没有解析定义的状态,您需要将其添加到 app.config 中:
var $delegate = $stateProvider.state;
$stateProvider.state = function(name, definition) {
if (!definition.resolve) {
definition.resolve = {};
}
return $delegate.apply(this, arguments);
};
在 stateChangeStart 中执行 if (!toState.resolve) { toState.resolve = {} };
似乎不起作用,我认为 ui-router 在它之后不接受解析字典已初始化。