我一直想了解这3个:

主题 BehaviorSubject ReplaySubject

我想使用它们,知道什么时候和为什么,使用它们的好处是什么,虽然我已经阅读了文档,观看教程和搜索谷歌,但我没有搞清楚这一点。

那么它们的目的是什么呢?如果是真实的情况,甚至不需要编写代码,那就最好不过了。

我更喜欢一个干净的解释,而不仅仅是“a+b => c您订阅了....”

谢谢你!


当前回答

     // ***********Subject  concept ***********
    let subject = new Subject<string>();


    subject.next("Eureka");
    subject.subscribe((data) => {
      console.log("Subscriber 1 got data >>>>> "+ data);
    });
    subject.subscribe((data) => {
      console.log("Subscriber 2 got data >>>>> "+ data);
    });

       // ********behaviour subject*********
    // Behavior subjects need a first value
let subject1 = new BehaviorSubject<string>("First value");


subject1.asObservable().subscribe((data) => {
  console.log("First subscriber got data behaviour subject>>>>> "+ data);
});
subject1.next("Second value")

Subject——订阅者只会在订阅之后获得已发布的值。 BehaviorSubject——新订阅者在订阅后立即获得最后发布的值或初始值。

其他回答

正如在一些帖子中提到的,公认的答案是错误的,因为BehaviorSubject != ReplaySubject(1),这不仅仅是编码风格的偏好。

评论中经常提到“守卫”,这也是我发现重放主题用例最多的地方。更具体地说,如果你有一个类似于取(1)的情况你不只是想取初值。

请看下面的例子:

  ngOnInit() {
    const behaviorSubject = new BehaviorSubject<boolean>(null);
    const replaySubject = new ReplaySubject<boolean>(1);
    this.checkLoggedIn(behaviorSubject, 'behaviorSubject');
    this.checkLoggedIn(replaySubject, 'replaySubject');
    behaviorSubject.next(true);
    replaySubject.next(true);
  }

  checkLoggedIn($userLoggedIn: Observable<boolean>, id: string) {
    $userLoggedIn.pipe(take(1)).subscribe(isLoggedIn => {
      if (isLoggedIn) {
        this.result[id] = 'routed to dashboard';
      } else {
        this.result[id] = 'routed to landing page';
      }
    });
  }

结果是:

{
  "behaviorSubject": "routed to landing page",
  "replaySubject": "routed to dashboard"
}

在这种情况下,你显然需要一个ReplaySubject!工作代码:https://stackblitz.com/edit/replaysubject-vs-behaviorsubject?file=src%2Fapp%2Fapp.component.ts

     // ***********Subject  concept ***********
    let subject = new Subject<string>();


    subject.next("Eureka");
    subject.subscribe((data) => {
      console.log("Subscriber 1 got data >>>>> "+ data);
    });
    subject.subscribe((data) => {
      console.log("Subscriber 2 got data >>>>> "+ data);
    });

       // ********behaviour subject*********
    // Behavior subjects need a first value
let subject1 = new BehaviorSubject<string>("First value");


subject1.asObservable().subscribe((data) => {
  console.log("First subscriber got data behaviour subject>>>>> "+ data);
});
subject1.next("Second value")

Subject——订阅者只会在订阅之后获得已发布的值。 BehaviorSubject——新订阅者在订阅后立即获得最后发布的值或初始值。

摘自:Randall Koutnik的书《用RxJS构建响应式网站》。”:

一个主题是一个对象,它是一个涡轮增压的可观察对象。就其核心而言,Subject的行为很像常规的可观察对象,但每个订阅都连接到相同的源。主体也是观察者,它们有next、error和done方法,可以一次性将数据发送给所有订阅者。因为主题是观察者,所以它们可以直接传递到订阅调用中,来自原始可观察对象的所有事件都将通过主题发送给它的订阅者。

我们可以用ReplaySubject追踪历史。ReplaySubject记录最近n个事件,并将它们回放给每个新订阅者。例如在聊天应用程序中。我们可以用它来追踪之前的聊天记录。

行为主体是ReplaySubject的简化版本。 ReplaySubject存储任意数量的事件,而BehaviorSubject只记录最新事件的值。每当BehaviorSubject记录一个新的订阅时,它都会向订阅者发出最新的值以及传递进来的任何新值。在处理单个状态单元(如配置选项)时,BehaviorSubject非常有用。

被点赞最多的回答显然是错误的:

如果你初始化一个ReplaySubject缓冲区大小为1,那么它的行为实际上就像一个BehaviorSubject


这并不完全正确;看看这篇关于两者区别的博客文章。例如,如果你订阅了一个完整的BehaviorSubject,你将不会收到最后一个值,但对于ReplaySubject(1),你将收到最后一个值。

这是一个不容忽视的重要区别:

const behavior = new behaviour subject (null); const replay = new ReplaySubject(1); behavior.skip(1)。订阅(v => console.log('BehaviorSubject:', v)); 重播。订阅(v => console.log('ReplaySubject:', v)); behavior.next (1); behavior.next (2); behavior.complete (); 的行为。订阅(v => console.log('晚期B订阅者:',v)); replay.next (1); replay.next (2); replay.complete (); 重播。订阅(v => console.log('后期R订阅者:',v));

查看这里的代码示例,它来自另一篇关于该主题的很棒的博客文章。

另一个不同之处在于,您可以使用BehaviorSubject的值getter来获取当前值。当您在某些情况下只需要当前值时,这是非常有用的。例如,当用户单击某个内容,而您只需要该值一次时。在这种情况下,你不需要订阅然后突然取消订阅。唯一需要的是:

BehaviorSubject bSubject = new BehaviorSubject<IBasket>(basket);

getCurrentBasketValue() {
  return this.bSubject.value;
}