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

Angular中APP_INITIALIZER依赖失效:EnvironmentService未定义

Angular APP_INITIALIZER 加载环境配置时 EnvironmentService 始终为 undefined 的问题

我尝试用 APP_INITIALIZER 在应用初始化阶段调用接口加载环境配置,但执行 runInitializers 时,EnvironmentService 一直是 undefined。这个功能最初在外部类库实现,类库代码如下:

// environmentService is undefined
function loadEnvironmentalValues(environmentService: EnvironmentService): () => Observable<EnvironmentValue> {
  return () => environmentService.getEnv().pipe(tap(() => console.log('ENV LOADED')));
}

@NgModule({
  declarations: [],
  imports: [HttpClientModule, NgxPermissionsModule],
  exports: [],
  providers: [
    EnvironmentService,
    {
      provide: APP_INITIALIZER,
      useFactory: () => loadEnvironmentalValues,
      deps: [EnvironmentService],
      multi: true
    }]
})
export class OurLibraryModule{
  constructor() {
  }
}

之后我在引用该类库的主应用里也试了相同逻辑,结果 EnvironmentService 还是 undefined:

// again environmentService is undefined
function loadEnvironmentalValues(environmentService: EnvironmentService): () => Observable<EnvironmentValue> {
  console.log('service je ', environmentService, !!environmentService);
  return () => environmentService.getEnv().pipe(tap(() => console.log('ENV LOADED from app')));
}

imports: [
    OurLibraryModule
],
providers: [
    EnvironmentService,
    {
      provide: APP_INITIALIZER,
      useFactory: () => loadEnvironmentalValues,
      deps: [EnvironmentService],
      multi: true
    },

EnvironmentService 的实现代码:

@Injectable({
  providedIn: 'root',
})
export class EnvironmentService {
  private readonly environmentValues$: Observable<EnvironmentValue>;

  constructor(private httpClient: HttpClient) {
    this.environmentValues$ = this.getEnvironmentValues().pipe(share());
  }

  getEnv(key?: string): Observable<EnvironmentValue> {
    if (key) {
      return this.environmentValues$.pipe(
        map((environmentConfig: EnvironmentValue) => environmentConfig[key])
      )
    } else {
      return this.environmentValues$;
    }
  }

  private getEnvironmentValues(): Observable<EnvironmentValue> {
    return this.httpClient.get<EnvironmentValue>(CONFIG_PATH).pipe(
      catchError((error: unknown) => {
        // eslint-disable-next-line no-console
        console.log('UNABLE TO LOAD ENVIRONMENT VALUES');
        // eslint-disable-next-line no-console
        console.error(error);
        throw error;
      }));
  }
}

想问下我遗漏了哪些配置?用 APP_INITIALIZER 前还要做什么前置操作吗?


问题原因及解决方案

1. APP_INITIALIZER 工厂函数写法错误

你的 useFactory 返回的是 loadEnvironmentalValues 函数本身,而不是调用该函数后返回的初始化函数。Angular 注入依赖后,需要工厂函数直接接收注入的服务实例,再生成初始化逻辑函数。正确写法应该是:

修改类库和主应用中的 APP_INITIALIZER 配置:

// 类库中的正确配置
{
  provide: APP_INITIALIZER,
  useFactory: (envService: EnvironmentService) => loadEnvironmentalValues(envService),
  deps: [EnvironmentService],
  multi: true
}

// 也可以直接简化写法
useFactory: (envService: EnvironmentService) => () => envService.getEnv().pipe(tap(() => console.log('ENV LOADED'))),

原来的写法中,useFactory: () => loadEnvironmentalValues 只是返回了函数本身,没有把注入的 EnvironmentService 传进去,导致 loadEnvironmentalValues 执行时参数为 undefined。

2. 移除重复的 EnvironmentService 提供

EnvironmentService 已经通过 providedIn: 'root' 声明为根注入服务,不需要在类库和主应用的 providers 数组中再次添加。重复提供可能导致注入实例不一致,甚至出现初始化异常。直接删除两处 providers 中的 EnvironmentService 即可。

3. 确保初始化流正常完成

Angular 的 APP_INITIALIZER 支持返回 Promise 或 Observable,返回 Observable 时 Angular 会自动订阅,但要确保接口能正常访问、流能正常完成。如果 CONFIG_PATH 错误或接口请求失败,会导致初始化中断,需要提前校验接口地址和权限。

修正后的类库模块代码示例

function loadEnvironmentalValues(environmentService: EnvironmentService): () => Observable<EnvironmentValue> {
  return () => environmentService.getEnv().pipe(tap(() => console.log('ENV LOADED')));
}

@NgModule({
  declarations: [],
  imports: [HttpClientModule, NgxPermissionsModule],
  exports: [],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: (envService: EnvironmentService) => loadEnvironmentalValues(envService),
      deps: [EnvironmentService],
      multi: true
    }]
})
export class OurLibraryModule{
  constructor() {
  }
}

主应用中的修正

移除 providers 中的 EnvironmentService,并修正 APP_INITIALIZER 的工厂函数:

function loadEnvironmentalValues(environmentService: EnvironmentService): () => Observable<EnvironmentValue> {
  console.log('service je ', environmentService, !!environmentService);
  return () => environmentService.getEnv().pipe(tap(() => console.log('ENV LOADED from app')));
}

imports: [
    OurLibraryModule
],
providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: (envService: EnvironmentService) => loadEnvironmentalValues(envService),
      deps: [EnvironmentService],
      multi: true
    },

内容的提问来源于stack exchange,提问作者Jakub Šmiga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:16:20