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
相关产品推荐
相关产品推荐

