如何在 ui-路由器解析器中重定向?
How to redirect in a ui-router resolver?
我正在尝试在 ui-路由器解析中进行重定向,想知道是否可以在路由器解析器中重新路由。目前这并不像人们想象的那样有效。
resolver(auth, $state){
if(!auth.isLoggedIn()){
$state.go('noLoggedInPath');
}
}
如何在解析器中正确重定向?
我的临时 hack 是这样的,但我不太适应。
resolver(auth, $state, $timeout){
if(!auth.isLoggedIn()){
$timeout(function () {
$state.go('noLoggedInPath');
}, 0);
}
}
您可以 return 来自 resolver
函数的承诺将指示是否继续导航至该州。如果您决定导航到其他地方 - 拒绝承诺并指定正确的状态:
resolver($q, $state, $timeout, auth) {
var deferred = $q.defer();
// $timeout is an example; it also can be an xhr request or any other async function
$timeout(function() {
if (!auth.isLoggedIn()) {
// user is not logged, do not proceed
// instead, go to a different page
$state.go('noLoggedInPath');
deferred.reject();
} else {
// everything is fine, proceed
deferred.resolve();
}
});
return deferred.promise;
}
Plunkr here.
UPD:更新了代码并添加了 plunkr。看起来它只有在你将它放在超时函数中时才有效。
Yauheni 的回答确实有效,但要解决奇怪的超时问题,您可以拒绝承诺,并在 $stateChangeError 事件中捕获它,然后在那里进行重定向。像这样...
state('admin', {
resolve: {
auth: function(UserService, $q, permissionService) {
var deferred = $q.defer();
return UserService.load().then(function(user){
if (permissionService.can(user, {goTo: state})) {
return deferred.resolve({});
} else {
return deferred.reject({redirectTo: 'some_other_state'});
}
});
}
}
});
然后 ui-路由器总是广播 "stateChangeError",所以你可以这样做..
$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
if (error.redirectTo) {
$state.go(error.redirectTo);
} else {
$state.go('error', {status: error.status})
}
})
这就是我实际做的,我找不到更好的解决方案
resolver($q, $timeout, myService) {
if(!areParameterValuesValid() || !isEverythingLogicallyOk()){
var deferred = $q.defer();
$timeout(function() {
$state.go('somewhere');
deferred.reject();
});
return deferred.promise;
} else {
return myService.loadSomething(passingSomeParams);
}
}
我用这个
function Check($state, $q) {
var deferred = $q.defer();
if (condition) {
deferred.resolve();
}
else {
deferred.reject();
}
return deferred.promise.catch(function () { $state.go('path'); });
}
您可以通过 redirectTo 配置使用解析器承诺
redirectTo: function($transition$) {
return $transition$.injector().getAsync('isNew').then(function(isNew) {
return isNew ? 'estate.edit' : 'estate.view';
});
},
我认为更简洁的答案是 return 已经被拒绝的承诺,例如:
resolver(auth, $state, $q){
if(!auth.isLoggedIn()){
$state.go('noLoggedInPath');
// Return rejected promise
return $q.reject();
}
return true;
}
为此使用 resolves 对我来说不太奏效。我改编了状态对象的 this post to execute a redirect function on the data 属性 的逻辑。然后,您可以从模块的 运行 块访问 $rootScope 上的 $stateChangeStart 事件,并使用注入器服务的 invoke 方法根据您指定的条件更改状态。跨模块也能很好地工作。
我正在尝试在 ui-路由器解析中进行重定向,想知道是否可以在路由器解析器中重新路由。目前这并不像人们想象的那样有效。
resolver(auth, $state){
if(!auth.isLoggedIn()){
$state.go('noLoggedInPath');
}
}
如何在解析器中正确重定向?
我的临时 hack 是这样的,但我不太适应。
resolver(auth, $state, $timeout){
if(!auth.isLoggedIn()){
$timeout(function () {
$state.go('noLoggedInPath');
}, 0);
}
}
您可以 return 来自 resolver
函数的承诺将指示是否继续导航至该州。如果您决定导航到其他地方 - 拒绝承诺并指定正确的状态:
resolver($q, $state, $timeout, auth) {
var deferred = $q.defer();
// $timeout is an example; it also can be an xhr request or any other async function
$timeout(function() {
if (!auth.isLoggedIn()) {
// user is not logged, do not proceed
// instead, go to a different page
$state.go('noLoggedInPath');
deferred.reject();
} else {
// everything is fine, proceed
deferred.resolve();
}
});
return deferred.promise;
}
Plunkr here.
UPD:更新了代码并添加了 plunkr。看起来它只有在你将它放在超时函数中时才有效。
Yauheni 的回答确实有效,但要解决奇怪的超时问题,您可以拒绝承诺,并在 $stateChangeError 事件中捕获它,然后在那里进行重定向。像这样...
state('admin', {
resolve: {
auth: function(UserService, $q, permissionService) {
var deferred = $q.defer();
return UserService.load().then(function(user){
if (permissionService.can(user, {goTo: state})) {
return deferred.resolve({});
} else {
return deferred.reject({redirectTo: 'some_other_state'});
}
});
}
}
});
然后 ui-路由器总是广播 "stateChangeError",所以你可以这样做..
$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
if (error.redirectTo) {
$state.go(error.redirectTo);
} else {
$state.go('error', {status: error.status})
}
})
这就是我实际做的,我找不到更好的解决方案
resolver($q, $timeout, myService) {
if(!areParameterValuesValid() || !isEverythingLogicallyOk()){
var deferred = $q.defer();
$timeout(function() {
$state.go('somewhere');
deferred.reject();
});
return deferred.promise;
} else {
return myService.loadSomething(passingSomeParams);
}
}
我用这个
function Check($state, $q) {
var deferred = $q.defer();
if (condition) {
deferred.resolve();
}
else {
deferred.reject();
}
return deferred.promise.catch(function () { $state.go('path'); });
}
您可以通过 redirectTo 配置使用解析器承诺
redirectTo: function($transition$) {
return $transition$.injector().getAsync('isNew').then(function(isNew) {
return isNew ? 'estate.edit' : 'estate.view';
});
},
我认为更简洁的答案是 return 已经被拒绝的承诺,例如:
resolver(auth, $state, $q){
if(!auth.isLoggedIn()){
$state.go('noLoggedInPath');
// Return rejected promise
return $q.reject();
}
return true;
}
为此使用 resolves 对我来说不太奏效。我改编了状态对象的 this post to execute a redirect function on the data 属性 的逻辑。然后,您可以从模块的 运行 块访问 $rootScope 上的 $stateChangeStart 事件,并使用注入器服务的 invoke 方法根据您指定的条件更改状态。跨模块也能很好地工作。