升级到Angular 9时出现MessagingService循环依赖问题如何解决
问题产生原因
Angular 9 版本默认启用了Ivy编译器,相比旧版本的ViewEngine,对依赖注入的循环引用检测严格度大幅提升,之前不会触发报错的隐式循环依赖在新版本会直接抛出异常。你当前遇到的问题本质是MessagingService和注入的ConfirmationService/MessageService存在隐式的互相引用,常见的场景有三类:
- 你项目内自定义了PrimeNG的全局消息/弹窗组件,该组件内注入了
MessagingService,同时该组件在根模块注册时和PrimeNG的ConfirmationService/MessageService形成了依赖绑定 - 你项目内的其他根级服务(比如HTTP拦截器、路由守卫)同时注入了
MessagingService和PrimeNG的消息类服务,形成了间接的循环依赖链 - 你使用的
@ngx-translate/i18n-polyfill的初始化逻辑间接依赖了消息服务相关实例,形成跨服务的循环引用
解决方案
你可以根据你的项目实际情况选择以下任意一种方案修复:
- 延迟注入有循环风险的服务:不要在构造函数中直接注入
MessageService和ConfirmationService,改为通过Injector在调用时按需获取,修改后的代码如下:
import { Injectable, Injector } from '@angular/core'; import { I18n } from '@ngx-translate/i18n-polyfill'; import { isNumber } from 'lodash'; import { ConfirmationService, MessageService } from 'primeng/api'; export enum ConfirmationType { Delete, Navigate, Unsaved, } export enum SuccessMessage { Cloned, Created, Deleted, Saved, Reverted, } @Injectable() export class MessagingService { // 通过getter延迟获取服务实例,避开初始化阶段的循环检测 private get _messageService(): MessageService { return this.injector.get(MessageService); } private get _confirmationService(): ConfirmationService { return this.injector.get(ConfirmationService); } constructor( private readonly _i18n: I18n, private readonly injector: Injector ) { }
- 调整服务作用域:不要将
MessagingService和PrimeNG的消息类服务都注册为根级单例,你可以将MessagingService改为在具体的功能模块中提供,或者拆分MessagingService的功能,把和PrimeNG服务耦合的逻辑抽成单独的子服务,断开循环链 - 排查并断开循环依赖链:梳理项目的依赖注入关系,找到和
MessagingService形成循环引用的服务,把两个服务共同依赖的逻辑抽成无其他依赖的公共工具服务,两边都依赖这个公共工具服务即可消除循环。
内容的提问来源于stack exchange,提问作者ShivamPatel
相关产品推荐
相关产品推荐

