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在线编辑器
相关推荐
xiaofeichaichai3 小时前
Webpack
前端·webpack·node.js
问心无愧05133 小时前
ctf show web入门111
android·前端·笔记
唐某人丶3 小时前
模型越来越强,我们还需要 Agent 工程吗?—— 从价值重估到 Harness 实践
前端·agent·ai编程
智码看视界3 小时前
现代Web开发基础:全栈工程师的起航点
前端·后端·c5全栈
JS菌4 小时前
手写一个 AI Agent 全栈项目:从沙箱执行到子智能体的完整实现
前端·人工智能·后端
excel5 小时前
HLS TS 文件损坏的元凶:Git 提交与拉取
前端
Aphasia3115 小时前
https连接传输流程
前端·面试
徐小夕5 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
threelab5 小时前
Three.js 物理模拟着色器 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器