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

Angular13:如何让useFactory等待APP_INITIALIZER加载完成?

解决Angular 13中工厂函数等待APP_INITIALIZER完成的问题

核心思路是让配置加载的异步逻辑被Angular初始化流程等待,同时让授权服务的工厂函数依赖已加载完成的配置。具体步骤如下:

1. 封装配置加载服务

先创建一个专门的配置服务,负责加载app-config.json并存储配置数据,确保配置加载是异步且可被等待的:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class AppConfigService {
  private configData: any;

  constructor(private http: HttpClient) {}

  // 加载配置并返回Promise,让Angular等待加载完成
  loadConfig(): Promise<void> {
    return this.http.get('/assets/app-config.json')
      .toPromise()
      .then(config => {
        this.configData = config;
      })
      .catch(err => {
        console.error('配置加载失败:', err);
        throw err; // 抛出错误阻止应用初始化,避免后续逻辑出错
      });
  }

  // 获取配置的方法,确保只有加载完成后才能拿到数据
  getConfig(): any {
    if (!this.configData) {
      throw new Error('配置尚未加载完成,请确保APP_INITIALIZER已执行');
    }
    return this.configData;
  }
}

2. 配置APP_INITIALIZER等待加载完成

在AppModule中配置APP_INITIALIZER,让Angular在启动应用前等待配置加载完成:

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppConfigService } from './app-config.service';

// 初始化函数,返回Promise让Angular等待
export function initializeApp(configService: AppConfigService) {
  return () => configService.loadConfig();
}

@NgModule({
  // ... 其他模块配置
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initializeApp,
      deps: [AppConfigService],
      multi: true // 允许多个初始化器
    }
  ]
})
export class AppModule {}

3. 改造授权服务的工厂函数

现在可以在工厂函数中安全注入AppConfigService,因为Angular已经确保配置加载完成,再根据配置选择对应的授权服务实现:

import { AbstractAuthorizationService } from './abstract-authorization.service';
import { LocalAuthorizationService } from './local-authorization.service';
import { ExternalAuthorizationService } from './external-authorization.service';
import { AppConfigService } from './app-config.service';

export function authServiceFactory(configService: AppConfigService): AbstractAuthorizationService {
  const config = configService.getConfig();
  // 根据配置中的授权类型选择实现类
  switch (config.authType) {
    case 'local':
      return new LocalAuthorizationService(); // 如果有依赖,需要注入对应的服务,比如HttpClient,要加到deps里
    case 'external':
      return new ExternalAuthorizationService();
    default:
      throw new Error(`不支持的授权类型: ${config.authType}`);
  }
}

// 在AppModule的providers中配置
@NgModule({
  providers: [
    // ... 其他provider
    {
      provide: AbstractAuthorizationService,
      useFactory: authServiceFactory,
      deps: [AppConfigService] // 依赖配置服务,确保配置已加载
    }
  ]
})
export class AppModule {}

注意事项

  • 如果LocalAuthorizationService或ExternalAuthorizationService本身有依赖(比如HttpClient),需要把这些依赖加到工厂函数的deps数组中,并在工厂函数中传入实例,比如:
    export function authServiceFactory(configService: AppConfigService, http: HttpClient): AbstractAuthorizationService {
      switch (configService.getConfig().authType) {
        case 'local':
          return new LocalAuthorizationService(http);
        // ...
      }
    }
    // 对应的deps: [AppConfigService, HttpClient]
    
  • 确保app-config.json放在assets目录下,或者调整http.get的路径,避免404错误。
  • 配置加载失败时要抛出错误,阻止应用初始化,避免后续因无配置导致的崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:05:25