2016-07-19 83 views
0

我不确定这是否是重复的,但我没有设法找到任何对我有用的东西,所以我发布了这个问题。承诺后的角度状态变化

我有一种情况,在将用户定向到某些路由之前,我需要从数据库获取值,以便我可以决定显示哪些内容。

如果我在$state.go(..)之前移动e.preventDefault(),那么它可以工作,但不正确。问题在于它开始加载默认状态,并且当它从http获得响应时,才会重定向到main.home。因此,假设数据库请求需要2秒钟的时间,那么在重定向到main.home之前需要2秒钟,这意味着用户会在大约2秒内看到它不应该出现的内容。

有没有办法在状态改变开始时防止默认值,并在状态改变结束时重定向用户? 另外,如果我们可以防止状态改变开始时的默认值,那么我们如何继续默认状态?

(function(){ 
    "use strict"; 
    angular.module('app.routes').run(['$rootScope', '$state', '$http', function($rootScope, $state, $http){ 
     /* State change start */ 
     $rootScope.$on('$stateChangeStart', function(e, to, toParams, from, fromParams){ 
      e.preventDefault(); 
      $http 
       .get('/url') 
       .error(function(err){ 
        console.log(err); 
       }) 
       .then(function(response){ 
        if(response.data === 2){ 
         // e.preventDefault() 
         $state.go('main.home'); 
        } 
        // direct to default state 
       }) 
     } 
    }]); 
}); 

回答

1

你可以添加一个resolve部分到$ stateProviderConfig。

在解决方案中,您可以向数据库发出请求并检查所需条件。如果您不希望用户访问此页面,则可以使用$ state.go()将其重定向到其他地方。

样本配置:

.state({ 
    name: 'main.home', 
    template: 'index.html', 
    resolve: { 
     accessGranted: ['$http', '$state', '$q', 
      function($http, $state, $q) { 
       let deffered = $q.defer(); 
       $http({ 
        method: 'GET', 
        url: '/url' 
       }).then(function(data) { 
        if (data === 2) { 
         // ok to pass the user 
         deffered.resolve(true); 
        } else { 
         //no access, redirect 
         $state.go('main.unauthorized'); 
        } 
       }, function(data) { 
        console.log(data); 
        //connection error, redirect 
        $state.go('main.unauthorized'); 
       }); 
       return deffered.promise; 
      } 
     ] 
    } 
}); 

resolve文档可以here

请注意,您可以使用Promise对象,而不是$ Q服务的情况下,你并不需要支持IE

+0

谢谢你,它的伟大工程。 (我想你应该在你的例子中注入$ q) – Timo

0

处理这种情况的一种方法是添加一个拦截器,如下所示。

.config(function ($httpProvider) { 
     $httpProvider.interceptors.push('stateChangeInterceptor'); 
    }).factory('stateChangeInterceptor', function ($q, $window,$rootScope) { 
     return { 
      'response': function(response) { 
       var isValid = true;//Write your logic here to validate the user/action. 
       /* 
       * Here you need to allow all the template urls and ajax urls which doesn't 
       */ 
       if(isValid){ 
        return response; 
       } 
       else{ 
        $rootScope.$broadcast("notValid",{statusCode : 'INVALID'}); 
       } 

      }, 
      'responseError': function(rejection) { 
       return $q.reject(rejection); 
      } 
     } 
    }) 

然后处理消息 'notValid' 如下

.run(function($state,$rootScope){ 
     $rootScope.$on("notValid",function(event,message){ 
     $state.transitionTo('whereever'); 
    }); 
})