[英]Why $state.go doesn't work when destination state or it's parent resolves with promise
我尝试使用resolve加载父状态的一些数据,并在应用程序运行时将用户重定向到默认状态:
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider.state('home', {
url: '/',
template: '<div><a ui-sref="home">Start App</a> <a ui-sref="home.main">Home</a> <a ui-sref="home.other">Other state</a><div ui-view>Loading...</div></div>',
resolve: {
user: ['$timeout', '$q',
function($timeout, $q) {
var deferred = $q.defer();
var promise = deferred.promise;
var resolvedVal = promise.then(function() {
console.log('$timeout executed');
return {Id: 12, email: 'some@email.com', name: 'some name'};
}, function() {
console.log('Error happend');
});
$timeout(function() {
deferred.resolve();
}, 2000);
return resolvedVal;
}]
//user: function() {return {id: 222, name: 'testname', email: 'test@em.ail'}; }
},
controller: ['$scope', 'user', function($scope, user) {
$scope.user = user;
}]
});
$stateProvider.state('home.other', {
url: 'other',
template: '<div>Your name is {{user.name}}, and email is {{user.email}}</div><div>This is other state of application, I try to make it open as default when application starts, by calling to $state.transitionTo() function in app.run() method</div>',
resolve: {
someObj: function() {
console.log('hello');
return {someProp: 'someValue'};
}
},
controller: ['$scope', 'user', function($scope, user) {
$scope.user = user;
}]
});
}]);
app.run(['$state', '$rootScope', function ($state, $rootScope) {
$state.go('home.other');
}]);
并且这不会更改地址栏中的url并且不显示home.other状态的模板(虽然home.state的解析功能已执行且控制台中有'hello')。 但是当我在解析中评论promise函数时,反而把简单的函数返回对象应用程序重定向到预期。
而不是$ timeout尝试做$ http请求实际上会在那里,但也没有运气。
并回答我自己的问题 - 由于在$ state.go('home.other')被调用之后,摘要周期开始处理请求的url并且当resolve函数创建了deffered对象时发生了不需要的行为,尽管此对象已解析,状态引擎已经传递到请求的URL状态。 所以为了防止这种情况,我使用了下面解释的技术:
如果在应用程序启动时需要在某些情况下放弃执行请求的URL状态解析,可以使用$ stateChangeStart事件,如下所示:
app.run(['$state', '$rootScope', '$timeout', function ($state, $rootScope, $timeout) {
var appStarted = 0; // flag to redirect only once when app is started
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
if(appStarted) return;
appStarted = 1;
event.preventDefault(); //prevents from resolving requested url
$state.go('home.other'); //redirects to 'home.other' state url
});
}]);
还有一个来自user3357257提供的相同链接的替代解决方案,我认为它有点清洁。
app.run(['$state', '$rootScope', '$timeout', function ($state, $rootScope, $timeout) {
$timeout(function() { $state.go('home.other'); });
}]);
诀窍是将$state.go()
包装到$timeout()
这样它就不会被覆盖。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.