Nestjs框架: 理解 RxJS响应式编程的核心概念与实践

概述

  • RxJS 是一个用于处理异步和基于事件编程的库,其核心理念是使用可观察序列(Observable Sequences)来构建程序逻辑
  • 你可以把它看作是处理事件的“lodash”,类似于 lodash 对数组和对象的操作,RxJS 则是对事件流的操作

1 )学习资源推荐

目前中文社区中有几个关于 RxJS 的文档网站可供参考:

  • cn.rx.js.org 官方文档,内容详尽,结构清晰;

  • rx.nodejs.cn 中文社区翻译版,适合中文用户;

  • rxjs.tech 翻译质量相对较高,推荐使用。

  • rxjs.dev 官网

  • 需要注意的是,文档中某些功能在文档中标记为划线

  • 表示这些方法可能已被弃用,或在未来的版本中不再支持

2 )核心概念解析

  • 官方介绍中提到:RxJS 是一个使用可观察序列编写异步和基于事件程序的库

  • 这句话可能初看有些晦涩,但其核心聚焦点在于两个方面:

    • 可观察序列(Observable Sequences)
    • 异步/事件处理能力
  • 为了更好地理解 RxJS,我们需要先了解其几个核心类型:

    • Observable(可观察对象):类似于 Promise,但它可以发出多个值,而不是只能解决一次;
    • Observer(观察者):用于监听 Observable 发出的值;
    • Subject(主体):一种特殊的 Observable,用于广播事件;
    • Operators(操作符):如 map、filter、reduce 等,用于处理事件流;
    • Scheduler(调度器):控制异步任务的执行方式,属于进阶概念。
  • 这些核心类型和操作符构成了 RxJS 的基础,使得我们可以将异步事件当作集合一样进行操作和处理

3 )实践示例:从事件监听到流式处理

  • 我们以一个简单的 DOM 事件监听为例,来看看 RxJS 如何处理事件

  • 传统的写法是:

    document.addEventListener('click', () => {
      // 处理点击事件
    });
    
  • 而使用 RxJS 后:

    import { fromEvent } from 'rxjs';
    fromEvent(document, 'click').subscribe(() => { console.log('Clicked!') });
    
  • 这里的 fromEvent 返回一个 Observable,通过 subscribe 方法进行订阅

  • 你也可以传入一个 Observer 对象,它包含三个回调方法:

    • next():每次事件触发时调用;
    • error():发生错误时调用;
    • complete():流结束时调用。
  • 这种写法不仅结构清晰,而且支持链式调用,便于管理状态

4 )操作符与流式控制:Purity 与 Flow

4.1 Purity

  • Purity(纯净性) 是 RxJS 的一大优势,它允许我们使用纯函数来生成值
  • 创建一个不纯的函数,举例,通常会弄乱你的状态
    let count = 0;
    document.addEventListener('click', () => console.log(`Clicked ${++count} times`));
    
  • 例如,我们可以使用 scan 操作符来实现点击计数,可以隔离状态
    import { fromEvent, scan } from 'rxjs';
    import { scan } from 'rxjs/operators';
    
    fromEvent(document, 'click')
      .pipe(scan((count) => count + 1, 0))
      .subscribe(count => console.log(`Clicked ${count} times`));
    
  • 在这个例子中,scan 类似于数组的 reduce 方法,每次点击都会将计数值递增,初始值是 0
  • 它可以把状态量在链式写法里面执行,不需要再外层单独定义了

4.2 Flow

Flow(流动) 是 RxJS 中另一个核心概念,它表示事件流的传递与变换
我们可以使用 pipe 函数将多个操作符串联起来,实现复杂的事件处理逻辑:
它把嵌套的函数调用变成了一种管道内参数传递的方式

下面是使用纯 JavaScript 实现“最多允许每秒单击一次”的方式:

let count = 0;
let rate = 1000;
let lastClick = Date.now() - rate;
document.addEventListener('click', () => {
  if (Date.now() - lastClick >= rate) {
    console.log(`Clicked ${++count} times`);
    lastClick = Date.now();
  }
});

使用 RxJS:

import { fromEvent, throttleTime, scan } from 'rxjs';

fromEvent(document, 'click')
  .pipe(
    throttleTime(1000),
    scan((count) => count + 1, 0)
  )
  .subscribe((count) => console.log(`Clicked ${count} times`));
  • 这里本质上是一个节流操作,这里的 pipe 方法让代码更具有可读性
  • 将嵌套的函数调用转化为参数传递的方式,使得事件流的处理逻辑更加清晰
  • 操作符中的管道文档 operators#piping

5 ) Values 与值的处理

Values(值转换) 是 RxJS 中处理流中数据的方式
可以通过你的 observables 传来的值进行转换

以下是使用纯 JavaScript 来为每次单击增加当前鼠标 x 位置的方法

let count = 0;
const rate = 1000;
let lastClick = Date.now() - rate;
document.addEventListener('click', (event) => {
  if (Date.now() - lastClick >= rate) {
    count += event.clientX;
    console.log(count);
    lastClick = Date.now();
  }
});

使用 RxJS之后

import { fromEvent, throttleTime, map, scan } from 'rxjs';

fromEvent(document, 'click')
  .pipe(
    throttleTime(1000),
    map((event) => event.clientX),
    scan((count, clientX) => count + clientX, 0)
  )
  .subscribe((count) => console.log(count));
  • 这里使用了 map 操作符提取事件中的值:

  • RxJS 提供了大量操作符

  • 这些操作符都可在官方文档的 Operators 分类中找到详细说明

6 ) 总结

RxJS 的几个核心概念

  • Observable、Observer、Subject、Operator、Scheduler
  • 如何使用 fromEvent 创建事件流
  • 如何通过 pipe 串联操作符处理事件流
  • 如何使用 scan、map、filter、throttleTime 等操作符进行事件处理
  • RxJS 与传统回调方式的区别:链式结构、状态管理、可维护性增强
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值