Angular懒加载模块获取共享库Service独立实例问题
Angular懒加载模块间共享单例服务重复实例问题
场景与问题
- RefreshService:需要作为全局单例在LazyModuleA、LazyModuleB两个懒加载模块间共享
- AppModule:懒加载模块加载前的基础模块
- SharedModule:包含RefreshService并打包为.tgz文件的类库
期望LazyModuleA和LazyModuleB获取同一个RefreshService实例,但在构造函数中添加控制台日志后发现,懒加载模块加载时会创建两个独立实例。
已尝试但无效的方案
- 为服务添加
providedIn: 'root'配置:
@Injectable({ providedIn: 'root'}) export class RefreshService {}
- 在SharedModule的
forRoot()方法中配置服务提供者:
export class SharedModule { static forRoot(): ModuleWithProviders<SharedModule> { return { ngModule: SharedModule, providers: [ RefreshService ] }; } }
- 导入配置:
- LazyModuleA、LazyModuleB中从tgz包导入
RefreshService并在构造函数中注入 - AppModule的
imports数组中调用SharedModule.forRoot()
- LazyModuleA、LazyModuleB中从tgz包导入
解决方案
1. 移除配置冲突
不要同时使用providedIn: 'root'和forRoot()中的providers配置,二者选其一即可。优先推荐providedIn: 'root',这是Angular官方推荐的单例服务声明方式,能自动在根注入器中注册服务,避免重复提供。
2. 检查类库的重复依赖
如果项目中存在多次安装shared-module的情况(比如根目录和懒加载模块子目录各自安装了一遍),会导致服务被多次打包,进而产生多个实例:
- 查看项目根目录及所有子模块的
package.json,确保shared-module仅在根目录的dependencies中声明 - 执行命令
npm ls shared-module查看依赖树,确认无重复依赖,若有则删除冗余安装并重新执行npm install
3. 禁止懒加载模块重复声明服务
检查LazyModuleA和LazyModuleB的@NgModule配置,确保它们的providers数组中没有声明RefreshService,否则懒加载模块会在自身注入器中创建新的服务实例。
4. 优化forRoot()方式(若坚持使用)
如果选择用forRoot()来提供单例服务,需做以下调整:
- 移除RefreshService上的
providedIn: 'root'配置 - 在SharedModule中添加防止重复导入的逻辑
- 仅在AppModule中调用
SharedModule.forRoot(),懒加载模块仅导入SharedModule(不调用forRoot())
调整后的代码示例:
// RefreshService.ts @Injectable() export class RefreshService {} // SharedModule.ts import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; export class SharedModule { static forRoot(): ModuleWithProviders<SharedModule> { return { ngModule: SharedModule, providers: [ RefreshService ] }; } // 防止懒加载模块重复导入并调用forRoot constructor(@Optional() @SkipSelf() parentModule?: SharedModule) { if (parentModule) { throw new Error('SharedModule 已在AppModule中加载,请勿在其他模块中重复导入'); } } }
内容的提问来源于stack exchange,提问作者awheedoy
相关产品推荐
相关产品推荐

