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

时间:2021-07-26 19:37:20

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). But when I comment promise function in resolve and instead put there simple function returning object application redirects as expected.

并且这不会更改地址栏中的url并且不显示home.other状态的模板(尽管home.state的解析函数已执行且控制台中有'hello')。但是当我在解析中评论promise函数时,反而把简单的函数返回对象应用程序重定向到预期。

Also instead of $timeout tried to do $http request which will actually be there, but no luck too.

而不是$ timeout尝试做$ http请求实际上会在那里,但也没有运气。

2 个解决方案

#1


10  

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. So to prevent this I used the technic explained below:

并回答我自己的问题 - 因为在$ state.go('home.other')被调用之后,摘要周期开始处理请求的url并且当resolve函数创建了deffered对象时发生了不需要的行为,尽管此对象已解析,状态引擎已经传递到请求的网址状态。所以为了防止这种情况,我使用了下面解释的技术:

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
  });  
}]);

#2


5  

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()中,这样它就不会被覆盖。

#1


10  

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. So to prevent this I used the technic explained below:

并回答我自己的问题 - 因为在$ state.go('home.other')被调用之后,摘要周期开始处理请求的url并且当resolve函数创建了deffered对象时发生了不需要的行为,尽管此对象已解析,状态引擎已经传递到请求的网址状态。所以为了防止这种情况,我使用了下面解释的技术:

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
  });  
}]);

#2


5  

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()中,这样它就不会被覆盖。