我正在写一个angular2 InterceptorModule ,这是大核心项目的一部分 . 每个模块都需要完全可配置和独立 . 所有模块都使用 foorRoot
方法编写,使我们能够实现全局单例并将任何配置传递给它 .
我们决定在主模块的 forRoot
metod中定义 HTTP_INTERCEPTORS
提供者 . 多亏了这个,我们在一个地方有一个配置,所有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
部分动态注入提供程序到 ModuleWithProviders
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 },
],
};
}
}
当然这个解决方案很糟糕,因为 forRoot
中定义的 HTTP_INTERCEPTORS
的数量是动态的 .
不工作的情况
解决方案就是动态注入提供者,如下所示:
@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;
}
}
这段代码导致异常:
ERROR in Error during template compile of 'AppModule' Function calls are not supported in decorators but 'CoreInterceptorModule' was called.
我读了一些关于这个问题的话题,但在我的案例中没有一个有用 . 问题是在 forRoot
方法中 return
语句之前无法调用任何函数 .
问题是如何在 forRoot
方法中动态添加 HTTP_INTERCEPTORS
?我想过像 useFactory
这样的东西但它接缝只能返回一个值(一个实例) .
1 回答
我解决了这个问题 . 我没有使用自定义配置类型
IInterceptorConfig
(后来无法迭代),而是创建了从原始Angular\@code\classProvider
继承的自定义Angular DI提供程序类型:感谢 I have my additional fields .
forRoot
方法配置如下所示:And finally and the most important I can dynamically fill ModuleWithProviders interface in sharedModule without errors :
它的工作原理是因为我使用数组扩展运算符(
...
)而不是任何其他函数调用 . 这个解决方案的唯一缺点是一些不必要的属性,如provide
,useClass
,multi
,它们无法封装在任何较低层 .