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

查看:24
本文介绍了在 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 中并不明显已经删除一次).

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(未记录的)服务在 Angular 2 中很好地扮演了 AngularJS 配置/运行块的角色(不包括异步初始化的功能).

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_INITIALIZERconfig<共享一些特征/code> 块也是如此,因为它用于在组件初始化之前配置服务并且容易受到竞争条件的影响(例如,由于 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天全站免登陆