RxJS入门概念理解

概述

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

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

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

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

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

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在线编辑器
相关推荐
架构技术专栏9 小时前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
别动我齐刘海9 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
志尊宝10 小时前
Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案
前端·css·笔记·vue·html·前端开发·软件开发
刘发财11 小时前
前端如何生成10000页PDF文件?
前端·javascript·开源
A接拉起00711 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户114818678948411 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界11 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
葡萄城技术团队11 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一12 小时前
优化修整算法
前端·javascript·算法
weifont13 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化