在Angular 2子模块中强制服务实例化(AngularJS运行块的替代方法) [英] Force service instantiation in Angular 2 sub-module (an alternative to AngularJS run block)

查看:101
本文介绍了在Angular 2子模块中强制服务实例化(AngularJS运行块的替代方法)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在子模块中有一个服务,该服务包装了一些第三方模块,实例化并初始化了其服务以准备在应用程序中使用.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆