RxJS入门概念理解

概述

RxJS 是一个使用可观察序列编写异步和基于事件的程序的库。它提供了一种核心类型,即 Observable、一些周边类型(Observer、Scheduler、Subjects)和类似于 Array 方法(mapfilterreduceevery 等)的操作符,以便将异步事件作为集合进行处理。

可以将 RxJS 视为处理事件的 Lodash。

RxJS 中解决异步事件管理的基本概念有:

  • Observable(可观察者) 表示未来(future)值或事件的可调用集合的概念。
  • Observer(观察者) 是一个回调集合,它知道如何监听 Observable 传来的值。
  • Subscription(订阅) 表示 Observable 的一次执行,主要用于取消执行。
  • Operator(操作符) 是纯函数,可以使用 mapfilterconcatreduce 等操作来以函数式编程风格处理集合。
  • Subject(主体: 相当于一个 EventEmitter,也是将一个值或事件多播到多个 Observers 的唯一方式。
  • Scheduler(调度器) 是控制并发的集中化调度器,允许我们在计算发生时进行协调,例如 setTimeoutrequestAnimationFrame 或其它。

让我们用简单的代码理解一下上面的概念

Observable-Observer-Subscription关系

js 复制代码
const { fromEvent, filter } from 'rxjs'

const click$ = fromEvent(document, 'click')  // 从文档的点击事件创建了Observable,即可观察者

const observer = { next: (event) => console.log(event) } // 创建Observer, 即观察者,包含一个 `next` 方法用于记录事件

const subs = click$  // 建立订阅对象,并传入观察者对象
            .pipe(filter((e) => e.clientY > 100)) // filter操作符,当返回结果为false时,不会触发后面的订阅函数
            .subscribe(observer); // 必须
    
subs.unsubscribe(); // 取消订阅

通俗一点讲就是,我们要观察document的点击事件(Observable),观察到了,我们就触发log方法(observer),但是我们只有通过pipe(管道)连接两者,并订阅(Subscription),才会通知到Observer。

用个例子,我要你去偷听一个人打电话然后告诉我,打电话就是可观察者(Observable),你就是观察者(Observer)观察到了之后干啥呢,告诉我(next事件),我要你去偷听是订阅(Subscription),如果没有订阅,你不会去听。中间你对我叙述听到的内容,你可以简短了说,也可以添油加醋的说,这就是中的操作符,你怎么操作的我不管,反正我听到的是你告诉我的内容。

说一下主体Subject

js 复制代码
const { fromEvent, filter, Subject, take } from 'rxjs'
 
const subject = new Subject(); // 创建主体对象,之后主要靠主体对象来进行广播

const click$ = fromEvent(document.getElementsByTagName('h1'), 'click');

// take是设定事件只触发两次,后面是将click$全部交给subject主体进行广播
click$.pipe(take(2)).subscribe(subject);

// 最后在有subject去建立Observe连接
const subs1 = subject.subscribe((e) => console.log(1));
const subs2 = subject.subscribe((e) => console.log(2));

    
subs1.unsubscribe(); // 取消订阅
subs2.unsubscribe(); // 取消订阅

广播顾名思义,就是一对多。 用上面的例子理解就是:subject理解为一个中介,我让你去听电话,他让你去看别人在干嘛,我们不直接对发号施令,而是通过中介。

调度器Schedule

在RxJS中,Schedulers(调度器)是用于控制 Observable 执行时的执行上下文(例如同步或异步)的一种机制。调度器允许你明确地定义 Observable 在何时、何地以及如何执行其操作。

简单说就是用来控制事件发出的顺序和速度的(发送给观察者的)。它还可以控制订阅 ( Subscriptions ) 的顺序。

RxJS 提供了几个内置的调度器,其中常见的包括:

  1. queueScheduler(队列调度器):

    使用 queueScheduler 时,操作会被放入一个队列,并在事件循环的下一个时刻执行。这是默认的调度器。

js 复制代码
const observable = from([1, 2, 3]); 

observable.pipe( 
     observeOn(queueScheduler)) // 使用队列调度器
    .subscribe(value => console.log(value));

使用 queueScheduler,操作会按顺序被放入队列,然后在下一个事件循环中执行。

  1. asapScheduler(asap 调度器):

    使用 asapScheduler 时,操作会在当前任务队列结束时(在当前宏任务结束前)尽快执行,这比 queueScheduler 更快。

js 复制代码
    import { asapScheduler, asyncScheduler, from } from 'rxjs';
    function syncSchedulerMain() {
        console.log('before');
        from([1, 2, 3]).subscribe(console.log)
        console.log('after');
    }
    syncSchedulerMain();
    // 执行结果:
    // before
    // 1
    // 2
    // 3
    // after

使用 asapScheduler,操作会在当前任务队列结束时(在当前宏任务结束前)尽快执行。

  1. asyncScheduler(异步调度器):

    使用 asyncScheduler 时,操作会被安排在一个微任务队列中,在当前任务执行完成后立即执行。这比 asapScheduler 更快。

js 复制代码
    function asyncSchedulerMain() {
        console.log('asyncScheduler: before');
        from([1, 2], asyncScheduler).subscribe(console.log)
        Promise.resolve('asyncScheduler: promise').then(console.log);
        console.log('asyncScheduler: after');
    }
    // 执行结果:
    // asapScheduler: before
    // asapScheduler: after
    // 1
    // 2
        // asapScheduler: promise

使用 asyncScheduler,操作会在微任务队列中被安排,在当前任务执行完成后立即执行。

  1. animationFrameScheduler(动画帧调度器):

    使用 animationFrameScheduler 时,操作会在浏览器的下一个动画帧中执行,通常用于与动画相关的场景。

调度器可以通过在 Observable 上使用 observeOn 操作符来指定

js 复制代码
const observable = from([1, 2, 3]); 

observable.pipe( 
     observeOn(animationFrameScheduler)) // 使用动画帧调度器
    .subscribe(value => console.log(value));

使用 animationFrameScheduler,操作会在浏览器的下一个动画帧中执行,通常用于与动画相关的场景。

RxJS相关辅助链接

  1. RxJS官网
  2. Rx Visualizer
  3. Rxjs动画演示对比
  4. 弹珠图
  5. RxJS在线编辑器
相关推荐
龙雨LongYu1210 分钟前
vue3+ts 我写了一个跟swagger.yml生成请求和响应实体(接口)
前端·vue.js·typescript
Stanford_11061 小时前
关于IDE的相关知识之一【使用技巧】
前端·ide·windows·微信小程序·微信公众平台·twitter·微信开放平台
_志哥_1 小时前
web开发环境下启动HTTPS服务访问
前端·javascript·https
爱健身的小刘同学1 小时前
安装 electron 依赖报错
前端·javascript·electron
耶啵奶膘1 小时前
uniapp+vue2+uview2.0导航栏组件二次封装
前端·javascript·uni-app
布兰妮甜1 小时前
如何使用 Tailwind CSS 构建响应式网站:详细指南
前端·css·tailwind css
MavenTalk1 小时前
前端技术选型之uniapp
android·前端·flutter·ios·uni-app·前端开发
ZZZCY20031 小时前
路由策略与路由控制实验
前端·网络
shawya_void1 小时前
javaweb-day01-html和css初识
前端·css·html
khatung1 小时前
React——useReducer
前端·javascript·vscode·react.js·前端框架·1024程序员节