【Angular中的RxJS】- Subject 分类介绍

        RxJS 中 Subject 是一种特殊类型的 Observable,它允许将值多播给多个观察者,所以 Subject 是多播的,而普通的 Observables 是单播的(每个已订阅的观察者都拥有 Observable 的独立执行)。

        代码中的定义:        

export declare class Subject<T> extends Observable<T> implements SubscriptionLike {}

        在 RxJS 中常用有四种 Subject 分别是:普通Subject,BehaviorSubject,AsyncSubject,ReplaySubject。

普通Subject

        普通 Subject 示例:

    let subject: Subject<number> = new Subject<number>();
    
    let count = 0;
    let intervalId = setInterval(() => {
      count++;
      if (count < 3) {
        subject.next(count);
      } else {
        subject.complete();
        clearInterval(intervalId);
      }
    }, 1000);

    subject.subscribe(
      data => { console.log(`1st subscribe: ${data}`) },
      (err) => { console.log(`1st subscribe err: ${err}`) },
      () => { console.log(`1st subscribe complete`) });

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`2nd subscribe: ${data}`) },
        (err) => { console.log(`2nd subscribe err: ${err}`) },
        () => { console.log(`2nd subscribe complete`) });
    }, 2000);

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`3rd subscribe: ${data}`) },
        (err) => { console.log(`3rd subscribe err: ${err}`) },
        () => { console.log(`3rd subscribe complete`) });
    }, 5000);

        运行结果:

         可以看到效果与 Hot Observables 一样, 在某个值被发出之后再添加的订阅,不能接收到该值及其之前发出的值。但是能收到完成通知。因此 Subject 是一种 Hot Observable。

BehaviorSubject

        Subject 的其中一个变体是 BehaviorSubject,它有一个“当前值”的概念。它保存了发送给消费者的最新值。并且当有新的观察者订阅时,会立即从 BehaviorSubject 那接收到“当前值”。

    let subject: BehaviorSubject<number> = new BehaviorSubject<number>(0);

    let count = 0;
    let intervalId = setInterval(() => {
      count++;
      if (count < 3) {
        subject.next(count);
      } else {
        subject.complete();
        clearInterval(intervalId);
      }
    }, 1000);

    subject.subscribe(
      data => { console.log(`1st subscribe: ${data}`) },
      (err) => { console.log(`1st subscribe err: ${err}`) },
      () => { console.log(`1st subscribe complete`) });

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`2nd subscribe: ${data}`) },
        (err) => { console.log(`2nd subscribe err: ${err}`) },
        () => { console.log(`2nd subscribe complete`) });
    }, 2100);

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`3rd subscribe: ${data}`) },
        (err) => { console.log(`3rd subscribe err: ${err}`) },
        () => { console.log(`3rd subscribe complete`) });
    }, 5000);

        运行结果:

        可以看到,第2个订阅在主体发出2之后进行添加也接收到了数值2(“当前值”)。

        为了更能体现与一般Subject的区别,可以将以上代码中的 subject.complete(); 注释掉,认为 Subject 未完成数据的推送。

        此时 使用一般Subject 的运行结果:        

        第2个和第3个订阅添加之后,主体未发出数据,所以都没有打印。

        使用BehaviorSubject 的运行结果:

         第2个和第3个订阅添加之后,主体未发出数据,但是都接收到了主体的当前值(最后一次发出的数据),所以都有打印2。

ReplaySubject

        ReplaySubject 类似于 BehaviorSubject,它可以发送旧值给新的订阅者,但它还可以记录 Observable 执行的一部分。

    let subject: ReplaySubject<number> = new ReplaySubject<number>(2);
    
    let count = 0;
    let intervalId = setInterval(() => {
      count++;
      if (count < 5) {
        subject.next(count);
      } else {
        subject.complete();
        clearInterval(intervalId);
      }
    }, 1000);

    subject.subscribe(
      data => { console.log(`1st subscribe: ${data}`) },
      (err) => { console.log(`1st subscribe err: ${err}`) },
      () => { console.log(`1st subscribe complete`) });

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`2nd subscribe: ${data}`) },
        (err) => { console.log(`2nd subscribe err: ${err}`) },
        () => { console.log(`2nd subscribe complete`) });
    }, 4000);

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`3rd subscribe: ${data}`) },
        (err) => { console.log(`3rd subscribe err: ${err}`) },
        () => { console.log(`3rd subscribe complete`) });
    }, 8000);

        运行结果:

         可以看到后面添加的订阅都接收到了最近推出的2个数据值,而且都收到了完成通知。

AsyncSubject

        AsyncSubject 是另一个 Subject 变体,只有当 Observable 执行完成时(执行 complete()),它才会将执行的最后一个值发送给观察者。

    let subject: AsyncSubject<number> = new AsyncSubject<number>();

    let count = 0;
    let intervalId = setInterval(() => {
      count++;
      if (count < 5) {
        subject.next(count);
      } else {
        subject.complete();
        clearInterval(intervalId);
      }
    }, 1000);

    subject.subscribe(
      data => { console.log(`1st subscribe: ${data}`) },
      (err) => { console.log(`1st subscribe err: ${err}`) },
      () => { console.log(`1st subscribe complete`) });


    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`2nd subscribe: ${data}`) },
        (err) => { console.log(`2nd subscribe err: ${err}`) },
        () => { console.log(`2nd subscribe complete`) });
    }, 3000);

    setTimeout(() => {
      subject.subscribe(
        data => { console.log(`3rd subscribe: ${data}`) },
        (err) => { console.log(`3rd subscribe err: ${err}`) },
        () => { console.log(`3rd subscribe complete`) });
    }, 6000);

        运行结果:

        可以看到,所有订阅都只接收到了主体完成前发出的最后一个数据。 

猜你喜欢

转载自blog.csdn.net/evanyanglibo/article/details/122188952