【问题标题】:rxjs shareReplay with refCount off doesn't subscribe to the source until the first downstream subscriber关闭 refCount 的 rxjs shareReplay 在第一个下游订阅者之前不会订阅源
【发布时间】:2020-11-02 13:32:50
【问题描述】:
export class DataService {
  private readonly dataSubject: Subject<Data> = new Subject();

  public readonly myData$: Observable<Data>;

  constructor() {
    this.myData$ = this.dataSubject.asObservable().pipe(
      shareReplay({
        bufferSize: 1,
        refCount: false,
      }),
    );
    // this would solve the problem, but is an ugly workaround
    // this.myData$.subscribe();
  }

  update(data: Data) {
    this.dataSubject.next(data);
  }

有这个全局单例DataService,它应该为应用程序的各个部分提供一定的数据。当消费者订阅时,他们应该立即收到最后一个值,以及未来的新值。

我的理解如下:如果我添加shareReplay,如上所示,关闭refCounting,它将订阅其上游可观察对象(即在这种情况下为dataSubject 并保留最后一个值,当有下游订阅者时,发出最后一个值以及任何未来的值。

如果我理解正确,会发生什么情况:如果第一个下游订阅者晚于主题源中的第一个值,则第一个值会丢失,因为那时shareReplay 没有订阅主题,所以它没有收集以前的值。如果我立即添加下游订阅者,则可以解决问题,但这有点难看。

我能够通过以下更好的解决方法解决我的问题,我将重播功能移到主题本身,因此无论订阅者如何,它都已经保留了最后的值。但仍然想知道我可能遗漏了什么shareReplay 是如何工作的,或者我在上面的代码中是否犯了错误。

export class DataService {
  private readonly dataSubject: Subject<Data> = new ReplaySubject();

  public readonly myData$: Observable<Data>;

  constructor() {
    this.myData$ = this.dataSubject.asObservable().pipe(
      share(),
    );
  }

  update(data: Data) {
    this.dataSubject.next(data);
  }

【问题讨论】:

  • 您可以尝试删除.asObservable() 吗?我认为那里失去了价值
  • 为什么不使用behaviourSubject?它将当前值发送给任何新订阅者:learnrxjs.io/learn-rxjs/subjects/behaviorsubject
  • @QuentinFonck 因为我不想指定初始值,因为任何值都是错误的。另外,如果您查看我的第二个代码 sn-p,我最终用ReplaySubject 解决了这个问题,但问题是shareReplay 解决方案有什么问题。

标签: angular rxjs


【解决方案1】:

使用Subject 时,如果next 发生在subscribe 之前,则该值将丢失。所以新订阅者无法获得最后一个值。因此建议使用ReplaySubjectBehaviorSubject 来避免丢失这样的值。

回答实际问题,如this article 关于shareReplay 中所述:

refCount: false 表示第一次订阅 ReplaySubject 时会订阅 Source

不,它不会立即订阅。

【讨论】:

  • 是的,我知道,但问题是关于shareReplay。与refCount: false 一起使用时不应该立即订阅吗?
  • @AlexBiro 我不知道实际订阅this.myData$ 的内容是什么,但订阅会在.subscribe 被调用时发生,不会很快。也许这篇文章可以帮助你理解itnext.io/…,请看“shareReplay() without refCount”位。
  • ahaaa,这可能是关键,来自链接的文章:refCount: false 表示在第一次订阅 ReplaySubject 时它将订阅 Source。 所以shareReplay 不会订阅上游 observable 直到第一个下游订阅者,即使使用refCount: false。您能否将其添加到您的答案中?我会接受它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多