2015-09-30 41 views
1

我想在我的角應用程序中建立某種形式的身份驗證,並想在用戶未登錄時重定向到外部URL(基於$ http.get )。

不知何故,當event.preventDefault()是$ stateChangeStart中的第一行時,我會以無限循環結束。

我已經看到有多個stackoverflow上的問題,像這樣說:「將event.preventDefault()置於else」中的state.go之前。但是,然後控制器被觸發,並且在返回承諾之前頁面已經顯示。

即使當我把在其他的event.preventDefault(),一個奇怪的現象發生了:

去根URL,它會自動添加/ stateChangeStart燒製#/後的URL和$多次。

app.js運行部分:

.run(['$rootScope', '$window', '$state', 'authentication', function ($rootScope, $window, $state, authentication) { 
    $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { 
     event.preventDefault(); 
     authentication.identity() 
     .then(function (identity) { 
      if (!authentication.isAuthenticated()) { 
       $window.location.href = 'external URL'; 
       return; 
      } else { 
       $state.go(toState, toParams); 
      } 
     }); 
    }); 
}]); 

authentication.factory.js標識()函數:

function getIdentity() { 
    if (_identity) { 
     _authenticated = true; 
     deferred.resolve(_identity); 
     return deferred.promise; 
    } 

    return $http.get('URL') 
    .then(function (identity) { 
     _authenticated = true; 
     _identity = identity; 
     return _identity; 
    }, function() { 
     _authenticated = false; 
    }); 
} 

編輯:添加了狀態:

$stateProvider 
    .state('site', { 
     url: '', 
     abstract: true, 
     views: { 
      'feeds': { 
       templateUrl: 'partials/feeds.html', 
       controller: 'userFeedsController as userFeedsCtrl' 
      } 
     }, 
     resolve: ['$window', 'authentication', function ($window, authentication) { 
      authentication.identity() 
      .then(function (identity) { 
       if (!authentication.isAuthenticated()) { 
        $window.location.href = 'external URL'; 
       } 
      }) 
     }] 
    }) 
    .state('site.start', { 
     url: '/', 
     views: { 
      '[email protected]': { 
       templateUrl: 'partials/start.html' 
      } 
     } 
    }) 
    .state('site.itemList', { 
     url: '/feed/{feedId}', 
     views: { 
      '[email protected]': { 
       templateUrl: 'partials/item-list.html', 
       controller: 'itemListController as itemListCtrl' 
      } 
     } 
    }) 
    .state('site.itemDetails', { 
     url: '/items/{itemId}', 
     views: { 
      '[email protected]': { 
       templateUrl: 'partials/item-details.html', 
       controller: 'itemsController as itemsCtrl' 
      } 
     } 
    }) 
}]) 

如果你需要更多的信息,或更多來自app.js的代碼讓我知道!

+0

您已經嘗試添加以下行:$ locationProvider.html5Mode(true);在你的路由配置中。並將此元數據添加到html標頭中:。這會驅逐你網址末尾的uggly /#。 –

+0

哦,是的,我忘記了html5mode()記錄,謝謝! – Ryaden

回答

1

$stateChangeStart不會等待您的承諾退出前解決。讓州等待承諾的唯一方法是在州的選項中使用resolve

.config(function($stateProvider) { 
    $stateProvider.state('home', { 
    url: '/', 
    resolve: { 
     auth: function($window, authentication) { 
     return authentication.identity().then(function (identity) { 
      if (!authentication.isAuthenticated()) { 
      $window.location.href = 'external URL'; 
      } 
     }); 
     } 
    } 
    }); 
}); 

通過從函數返回一個承諾,ui-router將不會初始化狀態,直到該承諾解決。

如果您有需要等待這個或其他國家的孩子,你需要在注入auth

wiki

的決心鍵必須被注入到孩子說明如果您想在實例化子項之前等待承諾解決。

+0

我實際上都有。因爲解決方案只會觸發一次(第一次加載頁面)。還是有辦法確保解決方案始終被觸發? – Ryaden

+0

是的,你可以使用'$ state.go()'的'reload'選項。但是如果您有其他解決方案,那麼這將是低效的,因爲它們也會被重新加載。 http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state –

+0

既然你正在緩存'_identity',你爲什麼要每次觸發它? –