微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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],SubmoduleInitializerService,{
            provide: APP_INITIALIZER,useFactory: () => () => {},deps: [SubmoduleInitializerService],multi: true
        }
    ]
})
class AppSubmodule {}

由于APP_INITIALIZER是多提供程序,因此它允许每个应用程序具有多个初始化函数,这些函数遵循加载模块的顺序.

对于同步初始化,更短(也可能更合适)的替代方法是将服务注入模块的构造函数

@NgModule({
    imports: [ThirdPartyModule],SubmoduleInitializerService
    ]
})
class AppSubmodule {
    constructor(sis: SubmoduleInitializerService) {}
}

正如在this answer中所解释的那样,APP_INITIALIZER也与配置块共享一些特性,因为它用于在组件初始化之前配置服务并且易受竞争条件的影响(例如,因为APP_INITIALIZER用于配置路由器,将其注入另一个APP_INITIALIZER将导致循环依赖).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐