javascript – 强制Angular 2子模块中的服务实例化(AngularJS运行块的替代)
作者:互联网
我在子模块中有一个服务包装一些第三方模块,实例化并初始化其服务以准备在app中使用.
@Injectable()
class SubmoduleInitializerService {
constructor (thirdPartyService: ThirdPartyService) {
thirdPartyService.initialize(...);
...
}
}
@NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService
]
})
class AppSubmodule {}
ThirdPartyService不是直接在app中注入,而是由其他ThirdPartyModule单元使用,因此只要SubmoduleInitializerService在与ThirdPartyService或父注入器相同的注入器中注入,一切都很好:
export class AppComponent {
constructor(
/* DO NOT REMOVE! BAD THINGS HAPPEN! */
submoduleInitializerService: SubmoduleInitializerService
) {}
...
}
事实证明这是一种糟糕的模式,因为如果SubmoduleInitializerService既不在类中也不在模板中使用(意外删除一次),那么为什么SubmoduleInitializerService应该在AppComponent中注入并不明显.
基本上,AppSubmodule模块需要替代Angular 1.x angular.module(…).run(…)块.
这里有什么选择?
解决方法:
APP_INITIALIZER
(未记录的)服务在Angular 2中相当好地扮演AngularJS配置/运行块的角色(不包括异步初始化的特性).
对于只是急切地实例化SubmoduleInitializerService的noop初始化块,它是:
@NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService,
{
provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [SubmoduleInitializerService],
multi: true
}
]
})
class AppSubmodule {}
由于APP_INITIALIZER是多提供程序,因此它允许每个应用程序具有多个初始化函数,这些函数遵循加载模块的顺序.
对于同步初始化,更短(也可能更合适)的替代方法是将服务注入模块的构造函数:
@NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService
]
})
class AppSubmodule {
constructor(sis: SubmoduleInitializerService) {}
}
正如在this answer中所解释的那样,APP_INITIALIZER也与配置块共享一些特性,因为它用于在组件初始化之前配置服务并且易受竞争条件的影响(例如,因为APP_INITIALIZER用于配置路由器,将其注入另一个APP_INITIALIZER将导致循环依赖).
标签:javascript,angular,typescript,angular2-services 来源: https://codeday.me/bug/20190727/1553859.html