为何将Observable置于服务中时RxJS share操作符未按预期工作?
1. 组件内使用方式
组件代码:
constructor() { const obs1 = interval(1000).pipe( tap(x => console.log('processing in comp1')), map(x => x * x), take(1), share() ); obs1.subscribe(x=>console.log('testShare1')) obs1.subscribe(x=>console.log('testShare2')) }
运行结果:
processing in comp1 testShare1 testShare2
此方式符合预期,share操作符正常生效,两次订阅共享同一份Observable执行流。
2. 外部服务调用方式
服务代码:
export class TestShareService { constructor() { } testShare() { const obs1 = interval(1000).pipe( tap(x => console.log('processing in service ')), map(x => x * x), take(1), share() ); return obs1; } }
组件代码:
constructor(private shareSrv: TestShareService) { shareSrv.testShare().subscribe(x=>console.log('testShare1 using service')); shareSrv.testShare().subscribe(x=>console.log('testShare2 using service')); }
运行结果:
processing in service testShare1 using service processing in service testShare2 using service
问题原因分析
这是正常现象,并非操作错误。问题出在服务的testShare()方法逻辑上:每次调用该方法都会创建一个全新的Observable实例,share()操作符只作用于当前创建的这个实例。两次调用testShare()得到的是完全独立的两个Observable,各自的订阅会触发各自的执行流,自然无法实现共享。
修正方案
要让服务中的Observable实现共享,需要将Observable实例作为服务的类属性,而非每次调用方法时创建新实例。修改后的服务代码如下:
export class TestShareService { // 将Observable作为类成员,只初始化一次 private obs1 = interval(1000).pipe( tap(x => console.log('processing in service ')), map(x => x * x), take(1), share() ); constructor() { } testShare() { return this.obs1; } }
此时两次调用shareSrv.testShare()会返回同一个Observable实例,share()操作符就能正常生效,两次订阅会共享同一份执行流,输出结果会和组件内使用的情况一致。
内容的提问来源于stack exchange,提问作者user3345721
相关产品推荐
相关产品推荐

