RxJS shareReplay设置refCount: true时的异常行为问询
问题现象
使用配置了refCount: true的shareReplay时,原本预期在没有活跃订阅时会取消订阅源Observable,但实际它似乎仍保留某种引用。我们在处理单次发射后完成的HTTP请求时遇到该问题,用of()复现了相同现象。
两个Observable的唯一区别在于一个末尾添加了take(1),但两种情况下的订阅都已完成并取消订阅。take操作符本应仅在N次发射后完成,看似多余却改变了行为。

可以看到,未添加take(1)的badObservable仍认为存在引用,不会取消订阅源,也不会重新执行请求。
更奇怪的是:若将take(1)从共享Observable移至调用端,定义时两个多播Observable完全相同,但必须通过goodObservable.pipe(take(1)).subscribe({...})调用才能让共享Observable正确取消/重新订阅源请求;如果直接调用goodObservable.subscribe,共享Observable会陷入停滞,后续永远不会取消订阅源(即不再发起HTTP请求)。关键是两种调用方式的订阅都显示已完成且处于closed/unsubscribed状态,从外部无法区分,开发者可能误以为无需添加take(1),却不知这会破坏底层Observable。
问题更新与解决方案
在GitHub上查询后发现多个相关问题,该行为曾被修改,不再重置已完成的Observable,这引发了持续的混淆。要实现refCount: true时预期的shareReplay功能,正确方式是使用share操作符:
share({ connector: () => new ReplaySubject(1), resetOnError: true, resetOnComplete: true, resetOnRefCountZero: true })
该方案可正常工作,但仍有疑惑:为何take(1)能规避此问题?即使是单次发射后完成的Observable(如HTTP请求),难道take会在源Observable完成前取消订阅并关闭?起初我以为take(1)每次订阅都会创建新的ReplaySubject,但延迟HTTP响应后多次订阅仍会共享同一请求,这一点无法理解。
内容的提问来源于stack exchange,提问作者JWrightII

