在Angular

时间:2018-02-21 09:51:07

标签: angular typescript

我有一个基本服务类,我在各种不同模块(由不同团队制作)中有多个不同的服务,这些服务继承自这个。我想在app启动时调用这些服务中常见的“init”函数。我不想在每个匹配此类型的服务上调用“init”,因为我很懒。

例如,在Java Spring中,我可以简单地使用基类注入整个集合,除了声明注入服务之外没有其他配置:

@Autowired
public void setServices(List<ProductService> productServices) { 
   for(ProductService service : productServices) {
      service.init();
   }
}

当然,直接类似的方式不起作用。

constructor(private _productServices: ProductService[]) {
   // Does not work
   _productServices.forEach(x => x.init());
}

有没有办法在Angular中轻松完成这项工作,还是我注定要手动启动所有服务?

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

以上是这个问题:https://stackblitz.com/edit/angular-esdmif

您需要以不同的方式提供所有服务:假设您有基类(不是接口,因为编译的JavaScript中不存在接口,因此Angular无法找到您想要的服务)和一对从您的基类继承的服务。

然后您提供以下服务:

providers: [
    { provide: BaseService, useClass: AService, multi: true },
    { provide: BaseService, useClass: BService, multi: true },
    { provide: BaseService, useClass: CService, multi: true },
    { provide: BaseService, useClass: DService, multi: true }
]

最后multi: true参数是必需的。

然后在您的组件中执行:

constructor(@Inject(BaseService) private services: BaseService[]) {
}

但这种方法存在一些问题:

  1. 您必须重写所有提供商
  2. 您将无法注入AService或BService等服务
  3. 由于您的服务分布在不同的模块中,因此最终会使用不同的注入器

答案 1 :(得分:1)

您可以使用注射令牌和多供应商轻松实现您的目标。使用注射令牌,您甚至可以使用接口进行注射。

创建注入令牌:

export const INIT_SERVICE = new InjectionToken<BaseService>('BaseService');

使用多标志提供令牌服务:

{ provide: INIT_SERVICE, useClass: Derived1Service, multi: true }

注入令牌并初始化您的服务:

constructor(@Inject(INIT_SERVICE) initServices: BaseService[]) {
  initServices.forEach(service => service.init());
}

工作示例here