我正在写一个angular2 InterceptorModule ,它是大核心项目的一部分。每个模块都需要完全可配置和独立。所有模块都使用foorRoot
方法编写,使我们能够实现全局单例并将任何配置传递给它。
我们决定在HTTP_INTERCEPTORS
主模块的metod中定义forRoot
个提供程序。多亏了这个,我们在一个地方有一个配置,所有URL规则都可以触发特定的拦截器。
这主要用于主要 AppModule 的import
部分:
CoreInterceptorModule.forRoot([
{
instance: TestInterceptor,
runConditions: [],
},
{
instance: MenuInterceptor,
runConditions: [InterceptorRunConditions.WhiteList],
whiteList: ['v1/'],
},
{
instance: MenuInterceptor,
runConditions: [
InterceptorRunConditions.WhiteList,
InterceptorRunConditions.BlackList
],
whiteList: ['v1/'],
blackList: ['v1/authorize']
},
]),
CoreStorageModule.forRoot({
mode: StorageMode.LocalStorage,
prefix: 'plCore',
modesPriority: [StorageMode.SessionStorage, StorageMode.Memory],
}),
我在将forRoot
部分的提供程序从 CoreInterceptorModule 动态注入ModuleWithProviders
时出现问题。
这是注入HTTP_INTERCEPTORS
:
@NgModule({})
export class CoreInterceptorModule {
static config(interceptorConfig: IInterceptorConfig[]): ModuleWithProviders {
return {
ngModule: CoreInterceptorModule,
providers: [
{ provide: INTERCEPTOR_CONFIG, useValue: interceptorConfig },
{ provide: HTTP_INTERCEPTORS, useClass: interceptorConfig[0].instance, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: interceptorConfig[1].instance, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: interceptorConfig[2].instance, multi: true },
],
};
}
}
当然这个解决方案很糟糕,因为HTTP_INTERCEPTORS
中定义的forRoot
数量是动态的。
解决方案就是动态注入提供者,例如:
@NgModule({})
export class CwaCoreInterceptorModule {
static forRoot(interceptorConfig: IInterceptorConfig[]): ModuleWithProviders {
// base module configuration
const moduleWithProviders: ModuleWithProviders = {
ngModule: CwaCoreInterceptorModule,
providers: [
{ provide: INTERCEPTOR_CONFIG, useValue: interceptorConfig },
],
};
// update HTTP_INTERCEPTORS array
interceptorConfig.forEach((e) => {
moduleWithProviders.providers.push({
provide: HTTP_INTERCEPTORS, useClass: e.instance, multi: true
});
});
return moduleWithProviders;
}
}
这段代码导致异常:
在AppModule'的模板编译期间出现错误错误 装饰器不支持函数调用,但是CoreInterceptorModule' 被称为。
我读了一些关于这个问题的话题,但在我的案例中没有一个有用。问题是在return
方法中forRoot
语句之前无法调用任何函数。
问题是如何在HTTP_INTERCEPTORS
方法中动态添加forRoot
?我想过像useFactory
这样的东西但它接缝只能返回一个值(一个实例)。
答案 0 :(得分:0)
我解决了这个问题。我没有使用自定义配置类型IInterceptorConfig
(后来无法迭代),而是创建了从原始Angular\@code\classProvider
继承的自定义Angular DI提供程序类型:
export interface InterceptorClassProvider extends ClassProvider {
runConditions: InterceptConditions[];
whiteList?: string[];
blackList?: string[];
}
感谢我有其他字段。 forRoot
方法配置如下所示:
CwaCoreInterceptorModule.forRoot([
{
provide: HTTP_INTERCEPTORS,
useClass: MenuInterceptor,
multi: true,
runConditions: [InterceptConditions.WhiteList],
whiteList: ['/v1']
},
]),
最后,最重要的是我可以动态填充sharedModule中的ModuleWithProviders
界面而不会出现错误:
static forRoot(interceptorProviders: InterceptorClassProvider[]): ModuleWithProviders {
return {
ngModule: CwaCoreInterceptorModule,
providers: [
{ provide: INTERCEPTOR_CONFIG, useValue: interceptorProviders },
...interceptorProviders
],
};
}
它的工作原理是因为我使用数组扩展运算符(...
)而不是任何其他函数调用。此解决方案的唯一缺点是一些不必要的属性,例如provide
,useClass
,multi
,这些属性无法封装在任何较低层中。