2017-08-30 56 views
2

我正在使用AngularJS ui-router。我正在嘗試爲未經身份驗證的用戶實施保護路由。我正在檢查用戶是否登錄在$stateChangeStart。如果用戶未登錄,則重定向到登錄狀態。

但是,當我在stateChangeStart處理程序使用$state.go("login"),處理程序代碼放在無限循環和獲得控制檯錯誤「的RangeError:最大調用堆棧大小超出」

下面是我的代碼:

$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams) { 
    var allowedStates = ["signup","confirmaccount","resetPassword"]; 
    if(!$window.localStorage.getItem('userInfo') && !(allowedStates.includes($state.current.name))) 
    { 
     $state.go("login"); 
    } 
} 
); 

以下是控制檯錯誤的截圖。

enter image description here

回答

2

阻止默認行爲,並檢查允許的狀態,而無需使用$state.current.name因爲toState已經到$stateChangeStart

更新

我覺得一個參數,你在這裏需要一個No State Change邏輯,而不是重定向到始終登錄。

$rootScope.$on('$stateChangeStart', 
    function(event, toState, toParams, fromState, fromParams) { 
    var noChangeStates = ["login", "signup", "confirmaccount", "resetPassword"]; 
    var noStateChange = noChangeStates.indexOf(toState.name) > -1; 

    if (noStateChange) { 
     return; 
    } 

    //Check for Allowed or Not Allowed logic here then redirect to Login 
    if (!$window.localStorage.getItem('userInfo')) { 
     event.preventDefault(); 
     $state.go("login") 
    } 
    } 
); 

請注意,您還應該加上「登錄」,以無狀態的改變

0

But when i am using $state.go("login") in stateChangeStart handler, the handler code goes in infinite loop and getting console error "RangeError: Maximum call stack size exceeded"

看起來你總是叫$state.go("login");

您可以檢查toStatefromState避免調用額外的時間$state.go("login");

喜歡的東西:

if(!$window.localStorage.getItem('userInfo') 
    && !(allowedStates.includes($state.current.name)) 
    && fromState.name !== 'login' 
){ 
    event.preventDefault(); 
    $state.go("login"); 
} 
0

使用stateChange事件不是處理該事件的最佳方式。其實,它的作用:

  • 您更改狀態
  • 然後你檢查認證。

最好在之前檢查改變狀態。對於這一點,你可以使用UI路由器的resolve

$stateProvider 
    .state('login', { // Login page: do not need an authentication 
    url: '/login', 
    templateUrl: 'login.html', 
    controller: 'loginCtrl', 
    }) 
    .state('home', { // Authenticated users only (see resolve) 
    url: '/home', 
    templateUrl: 'home.html', 
    controller: 'homeCtrl', 
    resolve: { authenticate: authenticate } 
    }); 

function authenticate($q, user, $state, $timeout) { 
    if (user.isAuthenticated()) { 
    // Resolve the promise successfully 
    return $q.when() 
    } else { 
    // The next bit of code is asynchronously tricky. 

    $timeout(function() { 
     // This code runs after the authentication promise has been rejected. 
     // Go to the log-in page 
     $state.go('logInPage') 
    }) 

    // Reject the authentication promise to prevent the state from loading 
    return $q.reject() 
    } 
} 

this answer見。

+0

謝謝您的回答。我曾嘗試過使用解決方案。但在這種情況下,我必須解決每個狀態的身份驗證功能。我不需要那個。我想使用狀態事件處理程序從一個地方檢查它。 –