rxjs series--Observale and Observer

Posted by gjdunga on Mon, 29 Jul 2019 11:32:58 +0200

In RxJS, the full flow of a data stream needs to contain at least Observable and Observer. Observable is the observer, Observer is the observer, Observer subscribes to Observable, Observable pushes data to Observer to complete the whole process.

It can be said that a complete RxJS data stream is an interactive game between Observable and Observer.

Observable implements the following two design patterns:

Observer model
Iterator pattern

Because it is not an article about design patterns, so once I have mentioned it, I can read the relevant books for myself. It is necessary to mention that any design pattern refers to the method of solving a particular type of problem. The problem is complex and changeable, which can not be solved by a single design pattern, but also requires the combination of multiple design patterns. Observable of RxJS is the combination of observer pattern and iterator pattern.

Interaction between Observale and Observer

Subscribe

First, we create an Observable as a data source.

 const { Observable } = rxjs;    const sourceObservable$ = new Observable(observer => {
        observer.next('hello');
        observer.next('rxjs');
    });

Then set up an observer as a subscriber

const Observer = {        next: res => console.log(res)
    };

Finally, Observer subscribes to Observable, and data begins to flow.

   sourceObservable$.subscribe(Observer);    // hello
    // rxjs

A very simple data stream is complete.

State flow

In the above example, only the next state is used to transfer data downstream continuously, but in fact, there are three states in the flow of data stream:

Next, normal flow to the next state
error, catch exception, flow aborted
complete, the data stream has been completed, and the flow terminates

Next, change the above code to add two other states

const sourceObservable$ = new Observable(observer => {
        observer.next('hello');
        observer.error('the data is wrong!');
        observer.next('rxjs');
        observer.complete();
    });    const Observer = {        next: res => console.log(res),        error: err => console.log(err),        complete: () => console.log('complete!')
    }

    sourceObservable$.subscribe(Observer);    // hello
    // the data is wrong!

Now let's see if Observer has a sense of deja vu? Yes, Observer is actually an iterator.

So far, it is not difficult to find that the interaction process between Observable and Observer is actually that Observer injects an iterator into Observable through the observer mode, controls the data flow of Observable through the next cursor, and transfers the state flow to error or complete according to the possible situation in the actual flow process.

unsubscribe

Observable and Observer are now connected through subscribe, but sometimes we need to disconnect this connection, such as when components are destroyed. At this point, you need to cancel your subscription. See the following example

const sourceObservable$ = new Observable(observer => {        let number = 1;
        setInterval(() => {
            observer.next(number++);
        }, 1000);
    });    const Observer = {        next: res => console.log(res),        error: err => console.log(err),        complete: () => console.log('complete!')
    }    const subscription = sourceObservable$.subscribe(Observer);

    setTimeout(() => {        // unsubscribe
        subscription.unsubscribe();
    }, 4000);    // 1
    // 2
    // 3
    // 4

It should be noted that in this example, although the subscription was cancelled, the source Observable $as the data source did not end because the complete method was never called, except that the Observer no longer received the pushed data.

To make it easier to observe the differences, we'll change sourceObservable $

const sourceObservable$ = new Observable(observer => {        let number = 1;
        setInterval(() => {            console.log('subscribe:' + number);
            observer.next(number++);
        }, 1000);
    });    // subscribe: 1
    // 1
    // subscribe: 2
    // 2
    // subscribe: 3
    // 3
    // subscribe: 4
    // 4
    // subscribe: 5
    // subscribe: 6
    // ...

Hot Observable and old Observable

Suppose we have a scenario where an Observable is subscribed to by two ObserverA and ObserverB N seconds apart, does ObserverB need to receive data before subscribing?

In fact, there is no fixed answer. Whether to receive or not depends on the actual business scenario. That's why there are Hot Observable and Cold Observable.

Hot Observable: Hot observable objects, similar to live broadcasts, start when you turn on live broadcasts, and the previous content has been missed. You can only receive data that starts at the moment of subscription.
Cold Observable: Cold Observable objects, similar to videos, start in the first second of the video you open. Each subscription receives data from scratch

Look at Hot Observable first. Each subscription only pushes the current data, so it will not reset the data push at each subscription. The code is as follows:

 // Generate data first
    let number = 1;    const sourceObservale$ = new Observable(observer => {        let num = number;
        setInterval(() => {
            observer.next(num++);
            number = num;
        }, 1000);
    });    const ObserverA = ObserverB = {        next: item => console.log(item),        error: err => console.log(err),        complete: () => console.log('complete!')
    }

    sourceObservale$.subscribe(ObserverA);

    setTimeout(() => {
        sourceObservale$.subscribe(ObserverB);
    }, 2000);    // 1 => A
    // 2 => A
    // 3 => A
    // 3 => B
    // 4 => A
    // 4 => B
    // ..

For Cold Observable, each subscription starts pushing again, so each subscription resets the data pushing. The code is as follows:

const sourceObservale$ = new Observable(observer => {        // Subscription generates data
        let number = 1;
        setInterval(() => {
            observer.next(number++);
        }, 1000);
    });    // No change in the middle
    ...    // 1 => A
    // 2 => A
    // 3 => A
    // 1 => B
    // 4 => A
    // 2 => B
    // ..

It can also be seen from this that Observable is inert in evaluation and only performs internal logic when it is subscribed, while Cold Observable goes further and does not even generate data when it is not subscribed.

Ruijiang Yun official website link: http://www.eflycloud.com/#register?salesID=6DGNUTUAV

Topics: Web Development