app.module文件中如何实例化providedIn: root服务用于模块forRoot配置
问题背景说明
你当前的写法无法直接生效的核心原因是:Angular 模块的imports数组配置阶段早于全局依赖注入容器初始化完成的时间,而设置了providedIn: 'root'的服务是在根注入器初始化时才会被实例化的,因此你没办法直接在@NgModule的imports配置里直接拿到EnvironmentService的实例。
以下是两种可行的解决方案:
方案1:调整目标模块的配置逻辑(推荐)
如果targetModule是你可以自行修改的模块,优先改用注入令牌的方式动态获取配置,完全符合Angular依赖注入规范:
- 首先在
targetModule中定义配置注入令牌:
export const TARGET_MODULE_CONFIG = new InjectionToken<{var1: string}>('TARGET_MODULE_CONFIG');
- 修改
targetModule的forRoot方法,改为接收配置提供者而非静态值:
static forRoot(configProvider: Provider): ModuleWithProviders<TargetModule> { return { ngModule: TargetModule, providers: [configProvider] }; }
- 在
targetModule内部需要用到配置的位置,直接注入EnvironmentService即可获取对应变量值。 - 最终你在
app.module里的配置写法如下:
imports: [ CommonModule, BrowserModule, BrowserAnimationsModule, HttpClientModule, AppRoutingModule, targetModule.forRoot({ provide: TARGET_MODULE_CONFIG, useFactory: (envService: EnvironmentService) => { return { var1: envService.var1 }; }, deps: [EnvironmentService] }), anotherModule, ],
方案2:第三方模块无法修改时的兜底方案
如果targetModule是不可修改的第三方包,必须在forRoot阶段传入静态配置值,可以在应用启动前手动实例化服务:
- 在
main.ts中手动创建注入器获取服务实例,挂载到全局对象:
import { EnvironmentService } from './path/to/environment.service'; import { Injector } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; const injector = Injector.create({ providers: [EnvironmentService] }); const environmentService = injector.get(EnvironmentService); (window as any).environmentService = environmentService; platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err));
- 在
app.module中直接读取全局的服务实例即可:
const environmentService = (window as any).environmentService; @NgModule({ imports: [ CommonModule, BrowserModule, BrowserAnimationsModule, HttpClientModule, AppRoutingModule, targetModule.forRoot({ 'var1': environmentService.var1 }), anotherModule, ], }) export class AppModule { }
注意:该方案仅适用于
EnvironmentService没有其他Angular运行时依赖(如HttpClient、Router)的场景,否则手动实例化会因找不到依赖报错。
内容的提问来源于stack exchange,提问作者MrPiotr84
相关产品推荐
相关产品推荐

