Angular11 TS4 依赖注入抽象类后Observable不触发原因排查
问题根本原因
这个异常的核心是 Angular依赖注入的实例化作用域规则和providedIn语义叠加导致的实例不一致问题,拆解来看:
- 首先明确你定义的
Class1Service配置了providedIn: 'root'的语义:当你以Class1Service本身作为DI令牌请求注入实例时,Angular会在应用根注入器下创建全应用唯一的单例,后续所有直接注入Class1Service的代码拿到的都是这个同一个实例。这个实例内部的ReplaySubject是被你的业务逻辑正常调用next()推送数据的,所以订阅它暴露的$obs回调可以正常触发,这就是你直接注入Class1Service时表现正常的原因。 - 当你在业务模块的providers中配置
{provide: Class1, useClass: Class1Service}时,会触发useClass的默认实例化逻辑:providedIn的自动单例注册逻辑,仅在该类自己作为DI令牌被请求时生效;一旦你显式在某个注入器的providers里用useClass指向Class1Service,Angular就会在当前业务模块的注入器作用域下,单独新建一个全新的Class1Service对象,完全不会复用根注入器下已经存在的那个Class1Service单例。这两个实例是相互独立的,各自持有自己的ReplaySubject,没有任何关联。 - 这个被新建的、仅存在于业务模块注入器作用域下的
Class1Service实例,从创建到销毁的全生命周期里,从来没有被业务逻辑调用过它内部obs的next()方法推送数据,所以你注入Class1拿到这个实例后,订阅它的$obs自然永远等不到回调触发。
补充说明:你复现代码里写的
new Replaysubject()是大小写笔误,正确写法应为new ReplaySubject(),如果代码中真的存在这个拼写错误,直接注入Class1Service时就会抛出实例化错误,不属于本次Observable不触发的根因。
解决方法
最直接的修复方式是将provider配置从useClass改为useExisting,避免Angular重复实例化:
providers: [ { provide: Class1, useExisting: Class1Service // 不再新建实例,直接复用当前注入器树中已有的Class1Service实例 } ]
修改后,注入Class1拿到的实例,和直接注入Class1Service拿到的是同一个根注入器下的单例对象,Observable的订阅逻辑就可以正常触发。
内容的提问来源于stack exchange,提问作者Simon k
相关产品推荐
相关产品推荐

