我正在开发一个Angular应用程序。在此,我将在进入仪表板之前对用户进行身份验证。为了达到这个目的,我写了signIn functionas
signIn function
登录功能
this.signIn = function(credentials) { console.info('AccountController[signIn] Called'); AuthService .login(credentials) .then(function(authenticatedUser) { $scope.globals['currentUser'] = authenticatedUser; AuthService.setCurrentUser(authenticatedUser); $scope.globals['isAuthenticated'] = true; $location.path('/dashboard'); }).catch(function(error) { console.warn('AccountController[signIn] :: ', error); Flash.Error(error); $scope.credentials.password = ''; }); };
我还想限制用户访问路由(如果尚未登录)。为此,我想到了this dirty code。
dirty code
路线
$stateProvider .state('signIn', { url: '/signIn', templateUrl: 'partials/signIn/signIn.html', data: { pageTitle: 'SignIn' }, controller: 'AccountController', controllerAs: 'ac', resolve: { auth: ['$q', 'AuthService', function($q, AuthService) { var userInfo = AuthService.isAuthenticated(); console.info('SignIn Route[isAuthenticated] :: ', userInfo); if (!userInfo) { return $q.when(userInfo); } else { return $q.reject({ isAuthenticated: true }); } }] } }) .state('dashboard', { url: '/dashboard', templateUrl: 'partials/dashboard.html', controller: 'DashboardController', access: { requiredLogin: true }, resolve: { auth: ['$q', 'AuthService', function($q, AuthService) { var authenticated = AuthService.isAuthenticated(); console.info('dashboard Route[isAuthenticated] :: ', authenticated); if (authenticated) { return $q.when(authenticated); } else { return $q.reject({ isAuthenticated: false }); } }] } }) .state('manageStudent', { url: '/manageStudent', templateUrl: 'partials/manageStudent.html', access: { requiredLogin: true }, resolve: { auth: ['$q', 'AuthService', function($q, AuthService) { var authenticated = AuthService.isAuthenticated(); if (authenticated) { return $q.when(authenticated); } else { return $q.reject({ isAuthenticated: false }); } }] } }); App.run(['$rootScope', 'settings', '$state', 'AuthService', '$location', function($rootScope, settings, $state, AuthService, $location) { $rootScope.$state = $state; // state to be accessed from view $rootScope.$settings = settings; // state to be accessed from view $rootScope.$on('$stateChangeStart', function(event, next,nextParams,prev,prevParams) { // If the user is logged in don't allow him to land on the Login Page if (next.access !== undefined) { if (next.access.requiredLogin && !AuthService.isAuthenticated()) { $location.path('/signIn'); } } }); $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) { event.preventDefault(); if (!error.isAuthenticated) { console.warn("I'm not Authenticated.Going to Sign-in"); return $location.path('/signIn'); } else { console.info("I'm Authenticated"); $location.path('/dashboard'); } }); }]);
我说上面的代码 DIRTY 的原因是,如果我要保护10条未授权用户使用的路由,则必须在所有路由中复制相同的resolve函数。
所以我的问题是,我应该怎么做才能摆脱多重解析功能并能够编写DRY代码?
由于auth应该在每次更改路线时都解决该问题,因此仅将其包装为单独的factory(这是一个单例并且仅运行一次)是不够的。为了解决这个限制,它应该是一个函数
auth
factory
app.factory('authResolver', function ($q, AuthService) { return function () { // ... }; });
在每条路线上运行
... resolve: { auth: function (authResolver) { return authResolver(); } }
仍然不是那种干燥,但这是推荐的湿度水平。
可能从样板中resolve节省一个并节省几行代码的更激进的方法将类似于以下内容:
resolve
app.run(function ($rootScope, authResolver) { $rootScope.$on('$stateChangeStart', function (e, to) { if (to.doAuthPlease) to.resolve.auth = authResolver(); }); });
和
... doAuthPlease: true, resolve: {}
提到的答案与ngRoute的明显区别是,在UIRouter中,您需要resolve定义对象才能动态地向状态添加新的解析器。可以像这样对待它,也可以照原样进行。