RxJS 入门

简介

  • 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

链接

代码