简体   繁体   English

为什么$ state.go在目标状态或其父级以承诺解析时不起作用

[英]Why $state.go doesn't work when destination state or it's parent resolves with promise

I tried to load some data on parent state with resolve and to redirect user to default state when the app runs like so: 我尝试使用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');   
}]);

And this does not change url in address bar and does not show template of home.other state (though the resolve function of home.state is executed and there is 'hello' in console). 并且这不会更改地址栏中的url并且不显示home.other状态的模板(虽然home.state的解析功能已执行且控制台中有'hello')。 But when I comment promise function in resolve and instead put there simple function returning object application redirects as expected. 但是当我在解析中评论promise函数时,反而把简单的函数返回对象应用程序重定向到预期。

Also instead of $timeout tried to do $http request which will actually be there, but no luck too. 而不是$ timeout尝试做$ http请求实际上会在那里,但也没有运气。

And to answer my own question - unwanted behavior happend because of digest cycle starts to handle requested url after $state.go('home.other') was called and as the resolve function creates deffered object, though this object is resolved, state engine already passes to the requested url's state. 并回答我自己的问题 - 由于在$ state.go('home.other')被调用之后,摘要周期开始处理请求的url并且当resolve函数创建了deffered对象时发生了不需要的行为,尽管此对象已解析,状态引擎已经传递到请求的URL状态。 So to prevent this I used the technic explained below: 所以为了防止这种情况,我使用了下面解释的技术:

If you need to discard execution of requested url's state resolvation in certain curcumstances when the application startes, you can use $stateChangeStart event, like this: 如果在应用程序启动时需要在某些情况下放弃执行请求的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
  });  
}]);

There is also an alternate solution from the same link provided by user3357257 which I think is a little bit cleaner. 还有一个来自user3357257提供相同链接的替代解决方案,我认为它有点清洁。

app.run(['$state', '$rootScope', '$timeout', function ($state, $rootScope, $timeout) {
  $timeout(function() { $state.go('home.other'); });   
}]);

The trick is to wrap $state.go() into $timeout() so that it doesn't get overridden. 诀窍是将$state.go()包装到$timeout()这样它就不会被覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM