简介
- RxJS 是一个使用可观察序列编写异步和基于事件的程序的库。
- 官方自认为
可以将 RxJS 视为处理事件的 Lodash
- 简单来说,在定义了一个
数据来源
,设置了一个来源监听
,在来源没有枯竭
,监听没有取消的情况下,会一直进行数据监听,并且可以加入管道
处理 - 与
Promise
基本上相同,在没有使用 RxJS 的情况下,Promise
也可以实现,只不过实现的理念不太一样 - 但是由于 RxJS 的设计,导致一些 debug 比较困难,如果遇到一些问题,很难定位,需要查源码+debug 查堆栈才能解决,所以在使用的时候不要有
唯rxjs
的观点,同样场景下,如果可以使用 Promise 并且没有问题,请使用 Promise对于新手来讲,Promise 往往比 RxJS 更可靠
- RxJS 简单的说就是订阅发布.没有订阅就没有发布,这是最基础的一点,需要记住
名词解释
英文 | 中文 | 语意化 |
---|---|---|
Observable | 可观察对象 | 承载操作的类 |
subscribe | 订阅 | 订阅有两种属性,一个是初始化时候定义这个订阅 中有什么样的操作,会返回什么样的值,一个是执行时作为方法,将观察者作为参数传进去,让观察者看到 有什么值,相当于 Promise 中的 resolve,reject(定义传入值)和 then(观察传入值) |
Observer | 观察者 | 值变化时我们应该如何处理 |
Subscription | 订阅处理 | 订阅 执行的时候,默认会一直执行,但是实际上有时候我们需要中断这个执行操作,所以就需要使用到这个 |
Subscriber | 订阅者 | 订阅者由观察者的参数实例化,并且继承了订阅处理,可以理解为即是观察者 又是订阅处理 |
Promise 与 Observable
- Promise 的意思为承诺,也就是不管成功与否,不管你看不看,我都要做,所以自然无法取消
- Observable 的意思为可观察对象,可以理解为只有进行
观察
了,才会触发变更,如果不观察
就不会变化遇事不决,量子力学
订阅与观察
- 宏观上两个词可以互用
- 比如 Observable 也可以改成可订阅对象,不进行订阅就没法产生值.都是一样的
- Subscriber 基本上可以代替 Observer(也就是说当我说订阅者的时候,其实就是观察者)
Observable
- RxJS 的核心,也是最基础的类
- 先订阅,后发布
- 不订阅,不发布
import { Observable } from 'rxjs';
(() => {
let instance = new Observable((subscriber) => {
subscriber.complete();
});
instance.subscribe({
complete: () => {
console.log('你好 rxjs');
},
});
})();
形象化
- 与其理解
观察
,订阅
等晦涩的词语,不如讲一个故事(用例如上) - 从前有个工厂(Observable),可以在生产线(定义 subscribe)上加工一种产品,每生产完一个,交付给客户(next),当加工完成后告知完成(complete)
当然工厂还可以加工其他产品
(subscriber) => {
subscriber.next(0);
subscriber.complete();
};
- 当客户下单时(调用 subscribe),工厂
开始工作
,客户持续对收到的产品进行处理(Observer),或者不满意时需要取消订单(Subscription.unsubscribe)每个客户对收到的产品(next)会进行不同的处理,当完成(complete)时会有不同的反应 每个客户下单时,都会启动一条新的生产线(定义 subscribe),但是加工产品的工序都是一样的,每个用户之间的生产线互不干扰
({
complete: () => {
console.log('你好 rxjs');
},
});
- 工厂做完了产品,告知客户完成(complete),整个流程结束,不支持退货
方法
构造
- 传入参数为
subscribe
,也可以理解为对subscribe
赋值,以便在后面调用
subscribe
- 执行传入
观察者
,返回订阅处理
订阅处理
可以理解为事件监听,当你不想监听的时候,需要取消监听,而这个时候一般都会定义一个 dispose 方法.这个订阅处理
中的unsubscribe
就和dispose
forEach
- 与
subscribe
基本相同,但是返回的是一个 Promise
pipe
- 管道方法,里面可以传入管道操作符
toPromise
- 已经弃用
- 使用
firstValueFrom
/lastValueFrom
函数代替 - 抛开返回值不谈,和 forEach 一样
Subject
- 继承于
Observable
- 发布给订阅
发布时,只会给已经订阅的,未订阅的不会收到
- 不订阅,也发布
import { Subject } from 'rxjs';
(() => {
let instance = new Subject();
instance.next('hello rxjs1');
instance.subscribe((result) => {
console.log(result);
});
instance.next('hello rxjs2');
})();
方法
next
- 执行时会将所有观察者发送 next
error
- 执行时会将所有观察者发送 error(一次性)
complete
- 执行时会将所有观察者发送 complete(一次性)
subscribe
- 将观察者加入数组,等待订阅执行(next,error,complete)
与 Observable 的不同
- Observable 在初始化的时候就已经定义好了
subscribe
以后每次执行,都是重复执行 - Subject 则是没有在初始时候定义
subscribe
,当执行的时候,会先将观察者注册上,等到使用next
,error
,complete
的时候,才会发送值,相对比较动态,不过观察者只能收到订阅后发送的值
BehaviorSubject
- 继承于
Subject
- 初始化的时候会给一个值(lastValue),每次发布时更新这个值(lastValue),每个订阅的第一个值,都是
lastValue
import { BehaviorSubject } from 'rxjs';
(() => {
let instance = new BehaviorSubject('hello world1');
instance.subscribe((result) => {
console.log('订阅1', result);
});
instance.next('hello world2');
instance.subscribe((result) => {
console.log('订阅2', result);
});
})();
与 Subject 的不同
- 自带一个 next 初始值,并且在每次订阅的时候,发送上一个发送 next 的值
subscribe
- 订阅时被执行的函数,通过 subscriber 的方法执行触发自己在
subscribe
方法中传入的函数
Observer(观察者)
- next 持续更新
- error 报错(仅一次)
- complete 完成(仅一次)
Observer Subscription Subscriber 的不同
- 观察者,只有观察,权限比较低,也是我们传入的都对象
- 订阅处理,订阅者的接口缩小,只有取消部分功能
- 订阅者,订阅了东西,不止要收到,还可以关键时候取消
订阅者=观察者+订阅处理
Subscription(订阅处理)
- 当观察者不想再接收信息了,可以关闭掉
方法
add
- 可以将其他的订阅处理(subscription2)加进来(subscription1),如果
subscription1
取消了,那么subscription2
也取消
remove
- 与 add 相反
操作符
- 凡是 Observable 都可以跟随管道符
创建操作符
同步创建类
- from
from([1]).subscribe((result) => {
console.log(result);
});
异步创建类
- timer
timer(0, 1000).subscribe((result) => {
console.log(result);
});
管道操作符(简称管道符)
同步映射类
- map
from([1])
.pipe(map((item) => item * 2))
.subscribe((result) => {
console.log(result);
});
Observable映射类
- switchMap
from([1, 2])
.pipe(switchMap((item) => of(item * 2)))
.subscribe((result) => {
console.log(result);
});
限制数量类
- take