将 CanActivate 与 LazyLoaded 模块和 Injectable 一起使用
Using CanActivate with LazyLoaded Module and Injectable
我有一个身份验证服务,它在我网站的管理员和用户部分都使用,但连接到后端 API 上的不同端点。我正在使用工厂根据加载的模块(管理员与用户)提供不同的服务。
但是,当我尝试创建 AuthGuard 服务并注入我的 AuthService 时,它总是在路由器调用 CanActivate 时生成一个单独的 AuthService 实例。路由器是否以某种方式在延迟加载模块的范围之外工作,这就是它生成新实例的原因?
auth.provider.ts
let AuthFactory = (
http: Http,
router: Router,
storageService: StorageService,
modalService: NgbModal,
isAdmin: boolean
) => {
return new AuthService(http, router, storageService, modalService, isAdmin);
};
export let AuthProvider = {
provide: AuthService,
useFactory: AuthFactory,
deps: [ Http, Router, StorageService, NgbModal, IS_ADMIN ]
};
app.routing.ts
const appRoutes: Routes = [
{
path: 'mgmt',
loadChildren: 'app/admin/admin.module'
},
{ path: '',
loadChildren: 'app/users/users.module'
},
{ path: '**',
redirectTo: ''
}
];
@NgModule({
imports: [ RouterModule.forRoot(appRoutes)],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
admin.routing.ts
RouterModule.forRoot(appRoutes);
const routes: Routes = [
{ path: '',
component: AdminComponent,
children: [
{
path: '',
component: DashboardComponent,
canActivate: [AuthGuard],
{
path: '**',
redirectTo: ''
}
]
}
];
@NgModule({
imports: [ RouterModule.forChild(routes)],
exports: [ RouterModule ]
})
export class AdminRoutingModule {}
auth-guard.service.ts
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService,
private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.authenticated()
.map(authenticated => {
if (authenticated) {
return true;
} else {
// do some other things
return false;
}
})
.take(1);
}
}
由于新使用了AuthFactory,您每次都在构建一个新的AuthProvider。您应该转向 "singleton" 设计模式,其中工厂提供构造函数,然后 getter 方法 returns 现有的 AuthProvider 或新的 AuthProvider(如果尚不存在)。这样你总是引用对象的单个实例。
在 javascript 中查看有关实现单例的大量资源。
我有一个身份验证服务,它在我网站的管理员和用户部分都使用,但连接到后端 API 上的不同端点。我正在使用工厂根据加载的模块(管理员与用户)提供不同的服务。
但是,当我尝试创建 AuthGuard 服务并注入我的 AuthService 时,它总是在路由器调用 CanActivate 时生成一个单独的 AuthService 实例。路由器是否以某种方式在延迟加载模块的范围之外工作,这就是它生成新实例的原因?
auth.provider.ts
let AuthFactory = (
http: Http,
router: Router,
storageService: StorageService,
modalService: NgbModal,
isAdmin: boolean
) => {
return new AuthService(http, router, storageService, modalService, isAdmin);
};
export let AuthProvider = {
provide: AuthService,
useFactory: AuthFactory,
deps: [ Http, Router, StorageService, NgbModal, IS_ADMIN ]
};
app.routing.ts
const appRoutes: Routes = [
{
path: 'mgmt',
loadChildren: 'app/admin/admin.module'
},
{ path: '',
loadChildren: 'app/users/users.module'
},
{ path: '**',
redirectTo: ''
}
];
@NgModule({
imports: [ RouterModule.forRoot(appRoutes)],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
admin.routing.ts
RouterModule.forRoot(appRoutes);
const routes: Routes = [
{ path: '',
component: AdminComponent,
children: [
{
path: '',
component: DashboardComponent,
canActivate: [AuthGuard],
{
path: '**',
redirectTo: ''
}
]
}
];
@NgModule({
imports: [ RouterModule.forChild(routes)],
exports: [ RouterModule ]
})
export class AdminRoutingModule {}
auth-guard.service.ts
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService,
private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.authenticated()
.map(authenticated => {
if (authenticated) {
return true;
} else {
// do some other things
return false;
}
})
.take(1);
}
}
由于新使用了AuthFactory,您每次都在构建一个新的AuthProvider。您应该转向 "singleton" 设计模式,其中工厂提供构造函数,然后 getter 方法 returns 现有的 AuthProvider 或新的 AuthProvider(如果尚不存在)。这样你总是引用对象的单个实例。
在 javascript 中查看有关实现单例的大量资源。