[RxJS in Angular]- Introduction to Subject Classification

        Subject in RxJS is a special type of Observable that allows values ​​to be multicast to multiple observers, so Subject is multicast, while ordinary Observables are unicast (each subscribed observer has an Observable performed independently).

        Definition in code:        

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

        There are four kinds of Subject commonly used in RxJS: ordinary Subject, BehaviorSubject, AsyncSubject, ReplaySubject.

Ordinary Subject

        Common Subject example:

    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);

        operation result:

         It can be seen that the effect is the same as that of Hot Observables. Subscriptions added after a value is emitted cannot receive the value and the values ​​emitted before it. But can receive completion notification. So Subject is a Hot Observable.

BehaviorSubject

        One variant of Subject is BehaviorSubject, which has a notion of a "current value". It holds the latest value sent to the consumer. And when a new observer subscribes, it will immediately receive the "current value" from the 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);

        operation result:

        It can be seen that the second subscription is added after the main body sends 2 and also receives the value 2 ("current value").

        In order to better reflect the difference from the general Subject, you can comment out the subject.complete(); in the above code, thinking that the Subject has not completed the data push.

        At this time, use the running results of the general Subject:        

        After the 2nd and 3rd subscriptions are added, the main body has not sent data, so they are not printed.

        The result of using BehaviorSubject:

         After the second and third subscriptions are added, the subject has not sent data, but both have received the current value of the subject (the last sent data), so they all print 2.

ReplaySubject

        ReplaySubject is similar to BehaviorSubject in that it can send old values ​​to new subscribers, but it can also record part of the Observable's execution.

    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);

        operation result:

         It can be seen that the subscriptions added later have received the two data values ​​recently launched, and have received notifications of completion.

AsyncSubject

        AsyncSubject is another Subject variant that only sends the last value of the execution to the observer when the Observable execution completes (executes 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);

        operation result:

        It can be seen that all subscriptions have only received the last data sent before the main body is completed. 

Guess you like

Origin blog.csdn.net/evanyanglibo/article/details/122188952