Rx 定义
Reactive Extension, 也叫ReactiveX,实践响应式编程的一套工具
An API for asynchronous programming with observable streams.
Rx 是一套通过可监听流来做异步编程的API。
Rx 几个基本概念
Observable(可被观察的对象)& Observer(观察者)
RxJS中的数据流就是Observable对象,Observable实现了两种设计模式:
- 观察者模式
其实就是大家比较熟悉的发布订阅模式
在RxJS中,通过Observable对象对象就是一个发布者,通过Observable对象的subscribe函数来订阅某个观察者Observer
- 迭代器模式
迭代器(Iterator)是一个接口,为各种不同的数据结构提供统一的访问机制。任何数据只要部署了 Iterator 接口,就可以完成遍历操作。
每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
Generator 函数是 ES6 提供的一种异步编程解决方案。执行 Generator 函数会返回一个迭代器(Iterator)对象。
一般通过返回的迭代器去主动调用next方法来控制整个异步执行的节奏。所谓“主动”就是当需要执行某个异步数据时需要去“拉”数据。
在Rx是其实是“推”数据,不过结合迭代器,可以多次"推"数据给观察者Observer
Subject(主题)
Subject 是允许值被多播到多个观察者的一种特殊的Observable。然而纯粹的Observable是单播的
注意:针对一个纯粹的可观察对象Observable而言,每当订阅某个观察者Obsrever都拥有单独的可观察对象Observable的执行 - 即每当Observable订阅某一个观察者Obsrever时,此时观察者Obsrever可以从头到尾得获取一个全新的可观察对象Observable的所有执行调用数据。
而相对于Subject而言,通过Subject订阅的观察者Observable只能拿到从订阅“此刻之后”的执行调用数据,之前的数据已被其他观察者消费掉了,过时不候。
Rx 中数据流的单播和多播
上述Subject中提及了多播的概念,下面介绍一下Obervable的单播和多播.
在Rx 中,Subject 既有Observable的接口,也具有Observer的接口。这样可以利用Subject 的两面性,来避免一个纯粹的Observable每订阅某个观察者均产生一个新的Observable的问题,从而实现多播。
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
const tick$ = interval(1000).pipe(take(3));
tick$.subscribe(value => console.log(`observer 1: ${value}`))
setTimeout(() => {
tick$.subscribe(value => console.log(`observer 2: ${value}`))
}, 2000);
// 输出结果:
observer 1: 0
observer 1: 1
observer 2: 0
observer 1: 2
observer 2: 1
observer 2: 2
// 在1.5s之后再订阅一个新的观察者后,发现新的观察依然能够获取tick$从0到2的“过时数据”。
// 说明一个纯粹的Observable,在每次被subscribe时都产生一个全新的数据流,和之前被subscribe的数据流完全互不干扰,同时进行数据的流动。
import { interval, Subject } from 'rxjs';
import { take } from 'rxjs/operators';
const tick$ = interval(1000).pipe(take(3));
const subject = new Subject();
tick$.subscribe(subject);
subject.subscribe(value => console.log(`observer 1: ${value}`))
setTimeout(() => {
subject.subscribe(value => console.log(`observer 2: ${value}`))
}, 1500);
// 输出结果:
observer 1: 0
observer 1: 1
observer 2: 1
observer 1: 2
observer 2: 2
// 在1.5s之后再订阅一个新的观察者后,发现新的观察已经拿不到“过时数据”0了。
// 通过将Subject作为“中间人”,Subject既可以作为观察者,也可以作为可观察对象,将监听到的数据原封不动的“推”给通过Subject订阅的观察者。此时,观察者们永远拿到的都是“实时数据”。