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

Angular类守卫转函数式守卫时inject()无法获取实例求助

问题:Angular函数式守卫中inject无法获取SSR_MANAGER实例

原基于类的守卫实现

import { isPlatformServer } from '@angular/common';
import { Inject, Injectable, Optional, PLATFORM_ID } from '@angular/core';

@Injectable()
export class Session2Guard implements CanActivate {
    constructor(
        @Inject(PLATFORM_ID) private platfirmId: Object,
        @Inject('SSR_MANAGER') @Optional() private ssrManager?: SsrManager
    ) {}

    canActivate(route: ActivatedRouteSnapshot): Observable<boolean | UrlTree> {
        if (isPlatformServer(this.platfirmId)) {
            this.ssrManager.preventSsr();
        }
    }
}

修改后的函数式守卫实现

import { inject, InjectionToken, PLATFORM_ID } from '@angular/core';
import { isPlatformServer } from '@angular/common';
import { CanActivateFn } from '@angular/router';
import { Observable, of } from 'rxjs';

export const SessionGuard: CanActivateFn = (): Observable<boolean> => {
    const platformId: Object = inject(PLATFORM_ID);

    const ssrManager: SsrManager = inject(new InjectionToken('SSR_MANAGER'), {
        optional: true,
    });

    if (isPlatformServer(platformId)) {
        return of(true);
    }
};

问题现象

将类守卫改为函数式守卫后,inject()始终无法获取到SSR_MANAGER的实例,返回值一直为null。

解决方案

问题核心在于DI令牌不匹配:

  • 原类守卫使用的是字符串令牌'SSR_MANAGER',而函数式守卫中每次调用inject时都新建了一个InjectionToken实例。Angular的DI系统是通过令牌的引用(而非名称字符串)来匹配依赖的,两者不属于同一令牌,因此无法找到对应实例。

调整方案二选一:

  1. 直接复用字符串令牌
    如果项目中是通过字符串令牌注册的SSR_MANAGER,直接传入字符串即可:

    const ssrManager: SsrManager = inject('SSR_MANAGER', { optional: true });
    
  2. 导入项目中已定义的InjectionToken常量(推荐)
    如果项目中原本就定义了对应的令牌常量,直接导入使用:

    // 假设项目中已在某个文件定义该令牌
    export const SSR_MANAGER = new InjectionToken<SsrManager>('SSR_MANAGER');
    
    // 在函数式守卫中导入并使用
    import { SSR_MANAGER } from './path-to-token-file';
    
    const ssrManager: SsrManager = inject(SSR_MANAGER, { optional: true });
    

额外补全逻辑

原类守卫中服务端环境调用ssrManager.preventSsr()的逻辑在函数式守卫中被遗漏,记得补全(同时用可选链避免null报错):

if (isPlatformServer(platformId)) {
    ssrManager?.preventSsr();
    return of(true);
}
// 补充客户端环境的返回逻辑,原代码也存在遗漏,需根据实际业务调整
return of(true);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 04:18:27