RxJS使用share操作符后Shared Observables仍未共享值的问题
问题原因
share操作符默认的重置机制是触发两次内部Promise调用的核心原因,它默认在三种场景下会重置上游Observable的多播状态,新的订阅会重新执行上游逻辑:
- 上游Observable抛出错误
- 上游Observable正常执行完成
- 所有活跃订阅者退订,引用计数归零
你当前的场景大概率是两次订阅为串行执行:第一次常规订阅触发Observable执行,内部Promise返回结果后第一次订阅完成,此时没有其他活跃订阅,引用计数归零,share自动重置了多播状态。之后forkJoin触发第二次订阅时,就会重新执行上游逻辑,导致Promise被调用两次。
解决方案
方案1:使用shareReplay永久缓存结果(最常用)
如果你需要这个Observable不管什么时候订阅都只执行一次,所有订阅者共享同一份结果,可以把share替换为带配置的shareReplay:
import { shareReplay } from 'rxjs/operators'; const yourObs$ = yourOriginalObs.pipe( // bufferSize:1 缓存最新的1个结果,refCount:false 关闭引用计数重置逻辑 shareReplay({ bufferSize: 1, refCount: false }) );
配置后第一次订阅会执行上游逻辑,后续所有订阅都会直接拿到缓存的结果,不会重新触发内部Promise。
方案2:修改share的重置配置
如果要继续使用share,可以关闭对应的重置开关:
import { share } from 'rxjs/operators'; const yourObs$ = yourOriginalObs.pipe( share({ resetOnComplete: false, // 上游完成后不重置 resetOnError: false, // 上游报错后不重置,不需要可以删除 resetOnRefCountZero: false // 引用计数归零后不重置,不需要可以删除 }) );
方案3:保证两次订阅并行执行
如果你的业务逻辑允许调整订阅时机,确保forkJoin的订阅在第一次订阅未完成前触发,两个订阅会共享同一次上游执行,也不会出现重复调用的问题。该方案依赖订阅时机,稳定性不如前两种。
内容的提问来源于stack exchange,提问作者Harsha Vardhan
相关产品推荐
相关产品推荐

