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在线编辑器
相关推荐
黄尚圈圈17 分钟前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水1 小时前
简洁之道 - React Hook Form
前端
正小安3 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光5 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   5 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   5 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web5 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常5 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇6 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器