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
相关产品推荐
相关产品推荐

