You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中如何仅在无现有实例时创建Injectable类型的新实例?

Angular 2+实现「无已存在实例才新建Injectable」需求的解决方案

报错原因

你遇到的循环依赖错误,是因为你在ColorsService的Provider依赖项中直接声明了ColorsService本身,Angular依赖注入系统解析时会重复触发当前Provider的实例化逻辑,陷入死循环因此抛出错误。

解决方案

不需要引入额外工具,直接通过Angular内置的修饰符@SkipSelf和@Optional调整依赖查找逻辑即可:

调整后的Provider代码

import { Optional, SkipSelf } from '@angular/core';

// 写在对应模块/组件的providers数组中
[
  {
    provide: MY_COLORS,
    useValue: ['#ff0000', '#00ff00', '#0000ff'] // 按需替换为你的颜色配置
  },
  {
    provide: ColorsService,
    useFactory: (
      @Optional() @SkipSelf() existingService: ColorsService,
      colors: string[]
    ) => {
      // 父层级存在实例直接复用,不存在则新建
      if (existingService) return existingService;
      return new ColorsService(colors);
    },
    deps: [
      [new Optional(), new SkipSelf(), ColorsService],
      MY_COLORS
    ],
  }
]

逻辑说明

  • @SkipSelf():要求注入器跳过当前层级(也就是正在定义ColorsService Provider的这个注入器),只从父级注入器查找实例,从根源避免循环依赖
  • @Optional():父级注入器找不到对应实例时返回null,不会抛出「Provider不存在」的错误
  • 你需要的MY_COLORS令牌只要在当前/父注入器中完成提供即可,不需要额外处理

扩展说明

如果你需要的是全局唯一单例,不需要自定义上述逻辑,直接给ColorsService添加注解即可:

@Injectable({
  providedIn: 'root' // Angular会自动全局维护唯一实例
})
export class ColorsService {
  constructor(@Inject(MY_COLORS) private colors: string[]) {}
}

只有当你需要实现「模块/组件级别的可选单例:父级提供就复用,父级没提供才在当前层级新建」的场景时,才需要自定义上述useFactory逻辑。

内容的提问来源于stack exchange,提问作者Vahid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 00:06:02