我需要根据运行时开关动态配置一些 Angular 服务。在 AOT 之前的几天,我使用以下代码让它工作:
@NgModule({
imports: [HttpModule],
providers: []
})
export class MyModule {
static forRoot(config: MyConfiguration): ModuleWithProviders {
return {
ngModule: MyModule,
providers: [
SomeService,
{
provide: SomeOtherService,
useFactory: (some: SomeService, http: Http) => {
switch (config.type) {
case 'cloud':
return new SomeOtherService(new SomethingSpecificForCloud());
case 'server':
return new SomeOtherService(new SomethingSpecificForServer());
}
},
deps: [SomeService, Http]
},
]
};
}
}
然后在我的AppModule
我会将其导入为MyModule.forRoot(myConfig)
.
当我更新 CLI 和 Angular 时,它不再编译,因为它无法进行静态分析。我明白为什么,但我仍然不确定解决它的正确方法是什么。
我是否滥用了这个forRoot()
首先采取什么方法?如何编写模块,以便根据运行时切换,它们产生不同的服务?
我找到了一种实现它的方法:通过提供者公开配置,然后注入“静态”工厂函数。上面的代码看起来像这样:
// Necessary if MyConfiguration is an interface
export const MY_CONFIG = new OpaqueToken('my.config');
// Static factory function
export function someOtherServiceFactory(config: MyConfiguration,some: SomeService, http: Http) {
switch (config.type) {
case 'cloud':
return new SomeOtherService(new SomethingSpecificForCloud());
case 'server':
return new SomeOtherService(new SomethingSpecificForServer());
}
}
@NgModule({
imports: [HttpModule],
providers: []
})
export class MyModule {
static forRoot(config: MyConfiguration): ModuleWithProviders {
return {
ngModule: MyModule,
providers: [
SomeService,
{ provide: MY_CONFIG, useValue: config },
{
provide: SomeOtherService,
useFactory: someOtherServiceFactory,
deps: [MY_CONFIG, SomeService, Http]
},
]
};
}
}
它确实有效,但我仍然很想知道这是否真的是一个好主意,或者我是否做了一些非常错误的事情并且应该采取完全不同的方法来解决这个问题。
我找到了另一个解决方案:
- 使用 Angular CLI 环境。
- 为不同环境具有不同实现或依赖关系的服务创建抽象类/接口。
- 从每个环境文件中导出正确的类型(谁说它只能是普通的 JS 对象?)。
- 在模块提供者定义中,导入来自环境.
- 在编译时,CLI 环境将链接正确的内容。
更多信息和示例项目位于my blog.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)