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

Angular 15:同作用域下同名Token注入值追加问题及解决

Angular多作用域同名Token合并实现方案

需求背景

父作用域通过SOME_TOKEN提供字符串"parent",子作用域提供同名Token(值为"child")时,需将值合并为列表["child", "parent"],且无法修改第三方库代码。

初次尝试:触发循环依赖

最初编写的provideToken函数因直接注入当前Token,触发循环依赖错误:

export const provideToken = (val: string) => {
  return {
    provide: SOME_TOKEN,
    useFactory: () => {
      const token = inject(SOME_TOKEN)
      return token ? [...token, val] : val
    }
  }
}

默认Angular仅返回最近作用域的Token值,曾考虑通过服务在构造函数追加值、ngOnDestroy中移除,但该方式易出错。

优化尝试1:skipSelf导致Token丢失

添加skipSelf配置后,共享模块的"shared"Token被忽略,仅能获取当前模块的"some"Token:

@NgModule({
  declarations: [SharedDirective],
  imports: [],
  exports: [SharedDirective],
  providers: [provideToken("shared")]
})
export class SharedModule {}


@NgModule({
  declarations: [SomeComponent],
  imports: [SharedModule],
  exports: [],
  providers: [provideToken("some")]
})
export class SomeModule {}

最终解决方案:multi:true + 数组扁平化去重

添加multi:true配置后无Token被忽略,但结果为嵌套数组,因此扩展库指令,在构造函数中扁平化数组并去重:

最终版provideToken函数

export const provideToken = (val: string) => {
  return {
    provide: SOME_TOKEN,
    useFactory: () => {
      const token = inject(SOME_TOKEN, {skipSelf: true, optional: true})
      return token ? [...token, val] : val
    },
    multi: true
  }
}

扩展指令的构造函数处理

// 扩展指令的构造函数
constructor(
    ...,
    @Optional()
    @Inject(SOME_TOKEN)
    providedToken: MaybeArray<string>,
    ...
) {
   if (Array.isArray(providedToken)) {
            providedToken = [...new Set(providedToken.flat(Infinity))]
   }
   super(..., providedToken, ...)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 03:15:27