Angular 提供者:使用现有的或创建一个(如果未提供)

Angular providers: Use existing or create one if not provided

在 Angular 2+ 中,如何仅在不存在实例的情况下提供 Injectable 的新实例?

我搜索并找到了 none,所以我尝试了 useFactory。到目前为止,这是我的代码:

{
  provide: ColorsService,
  useFactory: (colorService: ColorsService, colors: string[]) => {
    if (colorService) return colorService;
    return new ColorsService(colors);
  },
  deps: [ColorsService, MY_COLORS],
},

除了我手动注入 MY_COLORS 令牌这一事实之外,我还收到一个奇怪的错误:

Error: Circular dep for PghChartColorsService

所以在@eko 的帮助下,我找到了这个解决方案:

@Component({
  ...
  providers: [ColorsService],
})
export class ChildComponent {
  colorService: ColorsService;
  constructor(
    @Self() currentColorService: ColorsService,
    @Optional() @SkipSelf() parentColorService?: ColorsService,
  ) {
    this.colorService = parentColorService ?? currentColorService;
  }
}

在此示例中,parentColorService 是父组件可能提供的服务。如果未提供,我将使用在此组件中实例化的 currentColorSerivce(无论如何实例化,这可能不是一件好事)。

还有另一种方法可以实现。

{
  provide: ColorsService,
  useFactory: (parentInjector: Injector, colorService?: ColorsService) => {
    if (!colorService) {
        const injector = Injector.create({ providers: [{ provide: ColorsService }], parent: parentInjector });
        colorService = injector.get(ColorsService);
      }

      return colorService;
  },
  deps: [ Injector, [ new Optional(), new SkipSelf(), ColorsService ] ],
}

这样,每个 children 也将能够注入正确的服务