在Angular 2子模块中强制服务实例化(AngularJS运行块的替代方法) [英] Force service instantiation in Angular 2 sub-module (an alternative to AngularJS run block)
问题描述
我在子模块中有一个服务,该服务包装了一些第三方模块,实例化并初始化了其服务以准备在应用程序中使用.
I have a service in sub-module that wraps some third-party module, instantiates and initializes its service to prepare for use within app.
@Injectable()
class SubmoduleInitializerService {
constructor (thirdPartyService: ThirdPartyService) {
thirdPartyService.initialize(...);
...
}
}
@NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService
]
})
class AppSubmodule {}
ThirdPartyService
不是直接注入到应用程序中,而是由其他ThirdPartyModule
单元使用,因此,只要将SubmoduleInitializerService
注入到与ThirdPartyService
相同的注入器或父注入器中,一切都很好:>
ThirdPartyService
isn't injected in app directly but is used by other ThirdPartyModule
units, so as long as SubmoduleInitializerService
is injected in the same injector as ThirdPartyService
or parent injector, everything is fine:
export class AppComponent {
constructor(
/* DO NOT REMOVE! BAD THINGS HAPPEN! */
submoduleInitializerService: SubmoduleInitializerService
) {}
...
}
这被证明是一种糟糕的模式,因为不清楚SubmoduleInitializerService
为什么既不在课堂上也不在模板中使用的情况下,为什么仍要在AppComponent
中注入SubmoduleInitializerService
.
It was proven to be a lousy pattern because it is not obvious why SubmoduleInitializerService
should stay injected in AppComponent
if it's not used neither in class nor in template (was accidentally removed once already).
基本上AppSubmodule
模块需要Angular 1.x angular.module(...).run(...)
块的替代方案.
Basically AppSubmodule
module needs an alternative to Angular 1.x angular.module(...).run(...)
block.
这里有什么选择?
推荐答案
APP_INITIALIZER
(undocumented) service plays the role of AngularJS config/run blocks reasonably well in Angular 2 (not counting the feature of asynchronous initialization).
对于只是实例化SubmoduleInitializerService
的noop初始化块,它是:
For noop intialization block that just eagerly instantiates SubmoduleInitializerService
it is:
@NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService,
{
provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [SubmoduleInitializerService],
multi: true
}
]
})
class AppSubmodule {}
由于APP_INITIALIZER
是多提供者,因此它允许每个应用程序遵循加载模块的顺序具有多个初始化函数.
Since APP_INITIALIZER
is multi-provider, it allows to have several initialization functions per application that follow the order in which the modules are being loaded.
对于同步初始化,更短(可能更合适)的替代方法是将服务注入模块的构造函数中:
For synchronous initialization the shorter (and probably more appropriate) alternative is to inject the service into module's constructor:
@NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService
]
})
class AppSubmodule {
constructor(sis: SubmoduleInitializerService) {}
}
如此答案中所述,APP_INITIALIZER
也具有与config
块相同的特征,因为它是用于在组件初始化之前配置服务,并且容易受到竞争条件的影响(例如,由于使用APP_INITIALIZER
来配置Router
,因此将其注入到另一个APP_INITIALIZER
中将导致循环依赖).
As explained in this answer, APP_INITIALIZER
shares some traits with config
block, too, because it is used to configure services prior to component initialization and is susceptible to race conditions (for example, since APP_INITIALIZER
is used to configure Router
, injecting it into another APP_INITIALIZER
will result in circular dependency).
这篇关于在Angular 2子模块中强制服务实例化(AngularJS运行块的替代方法)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!