异步数据流的响应式编程库Rxjs(五)cold or hot

63 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

“热”的Observable和“冷”的Observable

Cold Observable

Cold Observable只有被Observers订阅的时候,才会开始产生值。是单播的,有多少个订阅就会生成多少个订阅实例,每个订阅都是从第一个产生的值开始接收,所以每个订阅收到的值都是一样的。不管观察者们什么时候开始订阅,源对象都会从初始值开始把所有的数都发给该观察者。

第一个例子

const { Observable, of } = require('rxjs');
const { take } = require('rxjs/operators');

// 用of创建了一个Observable
const ob$ = of(6,3,7);

ob$.subscribe((data) => {
    console.log(data);
});

console.log('End');

ob$.subscribe((data) => {
    console.log('第二个:', data);
});

6

3

7

End

第二个: 6

第二个: 3

第二个: 7

第二个例子

const { Observable, interval } = require('rxjs');
const { take } = require('rxjs/operators');

const ob$ = interval(1000).pipe(take(3));

ob$.subscribe((data) => {
    console.log(data);
});

console.log('End');

ob$.subscribe((data) => {
    console.log('第二个:', data);
});

运行结果:
End

0

第二个: 0

1

第二个: 1

2

第二个: 2

第三个例子

const { Observable, of } = require('rxjs');

const ob$ = new Observable((observer) => {
    observer.next(1);
    observer.next(2);
    observer.complete();
});

// 在v8里语法变了,这种写法就被废弃了,变成了一个参数
ob$.subscribe((data) => {
    console.log('第一个:', data);
}, null, () => {
    console.log('第一个完成');
});

ob$.subscribe((data) => {
    console.log('第二个:', data);
}, null,() =>{
    console.log('第二个完成');
});

第一个: 1

第一个: 2

第一个完成

第二个: 1

第二个: 2

第二个完成

第四个例子

const { Observable, of } = require('rxjs');

const ob$ = new Observable((observer) => {
    let count = 0;
    let intervalId = setInterval(() => {
        count++;

        if (count<3) {
            observer.next(count);
        }
        else {
            observer.complete();
            clearInterval(intervalId);
        }
    }, 1000);
});

ob$.subscribe((data) => {
    console.log('第一个:', data);
});

ob$.subscribe((data) => {
    console.log('第二个:', data);
});

第一个: 1

第二个: 1

第一个: 2

第二个: 2

Hot Observable

Hot Observables 不管有没有被订阅都会产生值。是多播的,多个订阅共享同一个实例,是从订阅开始接受到值,每个订阅接收到的值是不同的,取决于它们是从什么时候开始订阅。

第一个例子

const { Observable, of, publish } = require('rxjs');

const ob$ = new Observable((observer) => {
    observer.next(1);
    observer.next(2);
    observer.complete();
}).pipe(publish());

ob$.connect();

ob$.subscribe((data) => {
    console.log('第一个:', data);
}, null, () => {
    console.log('第一个完成');
});

ob$.subscribe((data) => {
    console.log('第二个:', data);
}, null,() =>{
    console.log('第二个完成');
});

publish: 这个操作符把一般的 Observable(Cold Observables )转换成ConnectableObservable。

ConnectableObservable: 是 Observable 的变种,属于 Hot Observable,会一直等待,直到 connnect 方法被调用才会开始把值发送给那些订阅它的观察者。

connect:ConnectableObservable 并不会主动发送值,通过调用 connect 方法,可以启动ConnectableObservable 发送值。当调用 connect 方法时,不管有没有被订阅,都会发送值。

运行结果:
第一个完成

第二个完成

因为connect会发射值,但此时的流并没有被订阅,当后面再被订阅时,为时已晚,流都已经完成了。

第二个例子

const { Observable, of, publish } = require('rxjs');

const ob$ = new Observable((observer) => {
    observer.next(1);
    observer.next(2);
    observer.complete();
}).pipe(publish());



ob$.subscribe((data) => {
    console.log('第一个:', data);
}, null, () => {
    console.log('第一个完成');
});

ob$.connect();

ob$.subscribe((data) => {
    console.log('第二个:', data);
}, null,() =>{
    console.log('第二个完成');
});


第一个: 1
第一个: 2
第一个完成
第二个完成

第三个例子

const { Observable, of, publish } = require('rxjs');

const ob$ = new Observable((observer) => {
    observer.next(1);
    observer.next(2);
    observer.complete();
}).pipe(publish());



ob$.subscribe((data) => {
    console.log('第一个:', data);
}, null, () => {
    console.log('第一个完成');
});

ob$.subscribe((data) => {
    console.log('第二个:', data);
}, null,() =>{
    console.log('第二个完成');
});

ob$.connect();


第一个: 1
第二个: 1
第一个: 2
第二个: 2
第一个完成
第二个完成

“冷”VS“热”

简单点说,就是一个像看直播,一个像是看录播。

  • Cold Observable:可以理解为点播(电影),我们打开的时候会从头播放;
  • Hot Observable:可以理解为现场直播,我们进场的时候只能看到即时的内容;

再来看一个例子:

const { Observable, publish, refCount } = require('rxjs');

const ob$ = new Observable((observer) => {
    observer.next(1);
    observer.next(2);
    observer.complete();
}).pipe(publish(),refCount());

ob$.subscribe((data) => {
    console.log('第一个:', data);
}, null, () => {
    console.log('第一个完成');
});

ob$.subscribe((data) => {
    console.log('第二个:', data);
}, null,() =>{
    console.log('第二个完成');
});

refCount:
Make a ConnectableObservable behave like a ordinary observable and automates the way you can connect to it.

运行效果:

第一个: 1

第一个: 2

第一个完成

第二个完成

是不是已经掌握了冷热流呢。