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

Angular Provider useFactory意外注入数组问题求助

Angular自定义InjectionToken注入结果为数组而非预期Observable类型

我在Angular中通过自定义InjectionToken配置了Provider,预期注入类型为Observable<Array<string>>,但实际注入的却是Observable<Array<string>>[],导致路由守卫中调用pipe时报错“authorizedRoutes$.pipe is not a function”。

相关代码如下:

注入令牌定义

export const AUTHORIZED_ROUTE_NAMES = new InjectionToken<Observable<Array<string>>>('Names of authorized routes');

app.module.ts中的Provider配置

providers: [
    // 其他配置
    { 
        provide : AUTHORIZED_ROUTE_NAMES, 
        useFactory: (routeService : RouteService) => routeService.authorizedRouteNames$, 
        deps: [RouteService], 
        multi: true
    },
    // 其他配置
]

RouteService代码

export class RouteService {

  private _authorizedRouteNames$$ : BehaviorSubject<Array<string>>;

  get authorizedRouteNames$() : Observable<Array<string>> {
    return this._authorizedRouteNames$$.asObservable();
  }

  // 从API获取值并调用_authorizedRouteNames$$.next()的代码
}

路由守卫报错代码

export const authorizedRouteGuard: CanActivateFn = (route, state) => {

    const authorizedRoutes$ = inject(AUTHORIZED_ROUTE_NAMES);

    // 逻辑处理
    const path = /** 从ActivatedRouteSnapshot获取 **/

    return authorizedRoutes$
        pipe(
          map((routes) => {
             return routes.indexOf(path) > -1;
          }
        )
}

问题原因

问题出在Provider配置中的multi: true参数:
当为InjectionToken的提供者设置multi: true时,Angular会将所有绑定到该令牌的提供者实例收集到一个数组中返回,而不是返回单个实例。你的注入令牌类型定义的是单个Observable<Array<string>>,但因为multi: true的存在,inject()实际返回的是该类型的数组,自然无法直接调用pipe方法。

解决方案

根据你的实际需求选择以下两种方案:

  1. 仅需单个提供者实例(推荐)
    直接移除Provider配置中的multi: true,这样inject(AUTHORIZED_ROUTE_NAMES)就会返回预期的单个Observable<Array<string>>实例:
providers: [
    // 其他配置
    { 
        provide : AUTHORIZED_ROUTE_NAMES, 
        useFactory: (routeService : RouteService) => routeService.authorizedRouteNames$, 
        deps: [RouteService]
        // 移除multi: true
    },
    // 其他配置
]
  1. 确实需要多个提供者实例
    如果你的业务场景需要多个地方为该令牌提供值,那么需要修改注入令牌的类型定义为数组类型,同时在路由守卫中处理数组中的每个Observable:
// 修改注入令牌类型
export const AUTHORIZED_ROUTE_NAMES = new InjectionToken<Observable<Array<string>>[]>('Names of authorized routes');

// 路由守卫中修改处理逻辑
export const authorizedRouteGuard: CanActivateFn = (route, state) => {
    const authorizedRoutesList$ = inject(AUTHORIZED_ROUTE_NAMES);
    const path = /** 从ActivatedRouteSnapshot获取 **/

    // 合并所有Observable的结果,比如取所有路由的并集
    return combineLatest(authorizedRoutesList$)
        .pipe(
            map(allRoutes => {
                const mergedRoutes = allRoutes.flat();
                return mergedRoutes.indexOf(path) > -1;
            })
        );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:05:15