如何通过.forRoot()配置依赖主应用服务填值的Angular外部库
解决方案
完全可以实现,你可以将forRoot设计为接收配置提供者,所有异步加载逻辑都放在主应用侧完成,FormatModule仅消费自身定义的注入Token,不会引入任何外部服务依赖。
步骤1:调整自定义库的FormatModule实现
首先修改FormatModule的forRoot方法,让它直接接收外部传入的配置提供者,库内部所有需要用到配置的逻辑都直接注入自身定义的FORMAT_CONFIG Token即可:
// Custom Library module import { NgModule, ModuleWithProviders, InjectionToken } from '@angular/core'; import { FormatConfig } from './format-config.interface'; // 修正原Token的泛型定义,和FormatConfig对应 export const FORMAT_CONFIG = new InjectionToken<FormatConfig>('FORMAT_CONFIG'); @NgModule({}) export class FormatModule { constructor() {} public static forRoot(configProvider: any): ModuleWithProviders<FormatModule> { return { ngModule: FormatModule, providers: [configProvider] }; } }
此时FormatModule仅依赖自身维护的接口和注入Token,和主应用的业务服务完全解耦。
步骤2:主应用侧配置异步加载逻辑
主应用侧实现异步加载的工厂函数,可配合APP_INITIALIZER保证配置在应用启动前加载完成,避免业务逻辑用到配置时数据还未返回:
// 主应用 AppModule import { APP_INITIALIZER, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormatModule, FORMAT_CONFIG } from 'your-custom-format-library'; import { ConfigService } from './services/config.service'; import { AppComponent } from './app.component'; // 异步加载配置的工厂函数 export function formatConfigFactory(configService: ConfigService) { return () => configService.extractFormatConfig().toPromise(); } @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, // 传入配置提供者到FormatModule FormatModule.forRoot({ provide: FORMAT_CONFIG, useFactory: formatConfigFactory, deps: [ConfigService] }), ], providers: [ ConfigService, // 可选:如果需要保证配置在应用启动前就加载完成,添加APP_INITIALIZER { provide: APP_INITIALIZER, useFactory: formatConfigFactory, deps: [ConfigService], multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }
补充说明
- 如果不需要在应用启动前就完成配置加载,可以去掉
APP_INITIALIZER的配置,Angular会在第一次注入FORMAT_CONFIG的时候自动执行工厂函数,等待异步结果返回后再完成注入。 - 如果使用Angular 14+版本,也可以用
EnvironmentProviders替代ModuleWithProviders,写法更简洁。
内容的提问来源于stack exchange,提问作者frankfullstack
相关产品推荐
相关产品推荐

