我有一些这样定义的路线:
$stateProvider .state('app', { url: '/', abstract: true, views: { 'menuContent': { templateUrl: 'templates/home.html' } } }) .state('app.restricted', { url: '/restricted', views: { 'content': { templateUrl: 'templates/restricted/restricted-dashboard.html', controller: 'RestrictedController as vmRestricted' } }, resolve: { isGranted: 'isGranted' } }) .state('app.restricted.pending', { url: '/pending', views: { 'tabsView': { templateUrl: 'templates/restricted/restricted-manage-pending.html', controller: 'RestrictedPendingController as vm' } }, resolve: { isGranted: 'isGranted' } }) .state('app.restricted.devices', { url: '/devices', views: { 'tabsView': { templateUrl: 'templates/trusted/restricted-manage-devices.html', controller: 'RestrictedDevicesController as vm' } }, resolve: { isGranted: 'isGranted' } }) .state('app.grant', { url: '/grant-access', views: { 'content': { templateUrl: 'templates/grant-access.html', controller: 'GrantAccessController as vm' } } }) ;
在这些路线中,我有一个禁区和一个授予访问权页面以授予对该禁区的访问权限。当isGranted解析提供者被拒绝时,我将重定向到该app.grant路由。
isGranted
app.grant
这是执行此操作的代码:
$rootScope.$on(AngularEvents.STATE_CHANGE_ERROR, _onStateChangeError); function _onStateChangeError(event, toState, toParams, fromState, fromParams, error){ switch (error) { case 'accessRejected': $state.go('app.grant'); break; } }
这是我的isGranted提供者的代码:
(function() { 'use strict'; angular.module('app') .provider('isGranted', isGrantedProvider); isGrantedProvider.$inject = []; function isGrantedProvider() { this.$get = isGranted; isGranted.$inject = ['$q', '$log', 'grantService']; function isGranted($q, $log, grantService){ $log.log('isGrantedProvider'); if (grantService.isGranted()) { return $q.when(true); } else { return $q.reject('accessRejected'); } } } })();
(grantService.isGranted()只返回一个布尔值)
grantService.isGranted()
我第一次app.restricted与$state.go('app.restricted')提供者一起去路线被执行。该路由被拒绝,因为未授予访问权限,我们被重定向到该app.grant路由。
app.restricted
$state.go('app.restricted')
在此页面中,用户可以登录并有权访问限制区域。一旦用户登录,我们会将其重定向到该app.restricted.pending路由,但不会调用解决方法,并且该路由将被拒绝,并且我们将app.grant再次重定向到该路由,而访问被授予。
app.restricted.pending
为什么不叫解决方案?有办法强迫它吗?
编辑
经过测试,我有新信息。
我看到只有在将解决方案作为服务时才第二次调用它:
当我们进入状态时,始终执行此解析:
state('app.restricted', { url: '/restricted', views: { 'content': { templateUrl: 'templates/restricted/restricted-dashboard.html', controller: 'RestrictedController as vmRestricted' } }, resolve: { isGranted: ['$log', function($log) { $log.log('RESOLVE'); }] } })
但是,即使我再次进入该状态,此解析也只会执行一次:
state('app.restricted', { url: '/restricted', views: { 'content': { templateUrl: 'templates/restricted/restricted-dashboard.html', controller: 'RestrictedController as vmRestricted' } }, resolve: { isGranted: 'isGranted' } }) angular.module('app') .provider('isGranted', isGrantedP); isGrantedP.$inject = []; function isGrantedP() { this.$get = isGranted; isGranted.$inject = ['$q', '$log']; function isGranted($q, $log){ $log.log('RESOLVE'); } }
为什么每次都不调用此服务?是因为服务是单例吗?我应该如何进行?
经过大量的调查和测试,我找到了解决方案!
首先,让我们看看为什么它不起作用
如文档中所述(http://angular-ui.github.io/ui- router/site/#/api/ui.router.state。$ stateProvider),如果解析为字符串,则对应于服务
factory-{string | function}:如果为string,则为服务的别名。否则如果是函数,则将其注入并返回将其视为依赖项的值。如果结果是一个承诺,则在将其值注入控制器之前对其进行解析。
正如angularjs docs(https://docs.angularjs.org/guide/providers)所述,所有服务都是单例,这意味着它将仅实例化一次
注意:Angular中的所有服务都是单例。这意味着注入器最多使用每个配方一次来创建对象。然后,注入器将参考保存为将来的所有需求。
它为什么如此重要?
因为解析不调用我们服务内部的函数。他们只使用实例化服务的返回值。 但是 因为我们的服务只会实例化一次,所以返回值将始终相同!(因为我们的服务初始化仅被调用一次)
我们可以做什么?
从我的测试中,我可以看到这样定义的解决方案:
resolve: { myResolve: ['$log', function($log) { $log.log('My Resolve!'); }] }
总是执行,因此我们可以用这种方式编写它们以使其正常工作。
但是,如果我想使用我的服务怎么办?
我发现能够使用我的服务并且具有类似于以下语法的最佳工作解决方案:myResolve: 'myResolveService'声明我的决心如下:
myResolve: 'myResolveService'
resolve: { myResolve: ['myResolveService', function(MyResolveService) { myResolveService.log(); }] }
我的服务是这样的:
angular.module('app') .factory('myResolve', myResolve); myResolve.$inject = ['$log']; function myResolve($log) { function service(){ this.log = log; function log() { $log.log('My resolve!'); } } return new service(); }
此代码也可以用于返回承诺的解决方案:
解决:
resolve: { myResolve: ['myResolveService', function(MyResolveService) { return myResolveService.check(); }] }
服务:
angular.module('app') .factory('myResolve', myResolve); myResolve.$inject = ['$q', 'myService']; function myResolve($q, myService) { function service(){ this.check = check; function check() { var defer = $q.defer(); if (myService.check()) { defer.resolve(true); } else { defer.reject('rejected'); } return defer.promise; } } return new service(); }