【问题标题】:How to have both ReplaySubject and BehaviorSubject functionality如何同时拥有 ReplaySubject 和 BehaviorSubject 功能
【发布时间】:2020-10-08 04:34:42
【问题描述】:

我有以下代码:

class MyClass {
  private readonly clientId$: ReplaySubject<string>;

  public get clientId(): Observable<string> {
    return this.clientId$;
  }

  constructor([... things]) {
    this.clientId$ = new ReplaySubject<string>(1);
    
    someObservable
      .pipe(
        map(arg => {
          // business logic and what not...
        }))
      .subscribe(clientId => {
        this.clientId$.next(clientId);
      });
  }
}

我希望能够使用myClassInstance.clientId.value();,例如像一个行为主体。除了 clientId 的新订阅者获得旧值之外,someObservable 很少触发。

有什么想法吗? 提前谢谢!

【问题讨论】:

  • 你为什么需要它? replaysubject 的缓冲区大小为 1,这本质上使其类似于 behaviorSubject。
  • 我希望能够在 rxjs 之外使用它,就像一个简单的值一样。
  • 你不能有另一个类变量并在你发出clientId的订阅块中分配最新的值吗?
  • BehaviorSubject 中的同步 getter 是 clientId.valueclientId.getValue() 而不是 clientId.value()。它BehaviorSubject 中可用。如果您需要,您可以为BehaviorSubject 使用默认值null,而不是在订阅中使用它。
  • BehaviorSubject 就是这样做的。如果您订阅 BehaviorSubject,您将获得它的当前(即最新)值。

标签: angular rxjs behaviorsubject


【解决方案1】:

虽然这不能直接回答您的问题,但我想指出您可能根本不需要主题!

订阅一个可观察对象,只是将值发送到您自己的主题中通常是不必要的。

在你的情况下,你不需要 ReplaySubject,你不需要 getter,你也不需要在你的构造函数中订阅。

这应该可以完成工作:

class MyClass {
    constructor(private someService:SomeService) { }

    clientId$ = this.someService.someObservable.pipe(
        map(val => val.clientId)
    );
}

就访问最新值而言...您可以将其存储在局部变量中:

clientId$ = this.someService.someObservable.pipe(
    map(val => val.clientId),
    tap(clientId => this.clientId = clientId)
);

但通常这也不是必需的。如果您在模板中使用async 管道,您已经获得了展开后的最新值。

<h3 *ngIf="clientId$ | async as clientId">{{ clientId }}</h3>

【讨论】:

  • 有一个微妙但重要的区别:通过主题多播源,您的方式不会。如果源很昂贵或不像网络请求那样具有幂等性,这将成为一个大问题。当然多播可以通过隐藏主题但仍然使用主题的运营商来实现。
  • 我也不确定问题的哪一部分让您说 OP 不需要重播客户端 ID。有很多正当理由需要这样做,没有关于他们想要做什么的信息,也没有关于源是否已经重播的信息。
  • 最后,您的答案跳过了与原始解决方案相比在错误处理方面的差异,这也可以发挥重要作用。总而言之,这里的意图是好的,但答案不够细致,无法盲目地建议不要使用主题。
  • 感谢您指出这些差异。你说得对,重要的是要注意多播和错误处理问题,并在适当的时候使用shareshareReplay 运算符。我的意图并不是完全避免使用主题,而是要指出一些我认为对许多 rxjs 新手来说并不明显的东西,那就是:你没有必须使用主题通过流“手动”推送值。将现有的可观察流转换为您需要的形状通常要简单得多。
  • 我同意,尤其是新来者经常跳到这一点的事实,因此我说这里的意图是好的(在很多方面我同意你的观点)。我的 cmets 并没有深入研究这些问题,但我希望他们为答案添加一些背景信息,以供考虑。干杯。
猜你喜欢
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多