JavaScript (Node.js) 中的响应式编程:RxJS 与 Observables

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

使用 RxJS 库在 JavaScript (Node.js) 中进行响应式编程



响应式编程是一种面向异步数据流和变化传播的编程范式。在 Node.js 生态系统中,这一概念通过 RxJS(JavaScript 的响应式扩展)库来实现。与传统的回调或 Promise 方式不同,RxJS 提供了 Observable 对象,用于表示随时间变化的数据流。



核心概念



RxJS 的核心包含三个关键实体:



  • Observable — 数据源,可以随时间生成值(如鼠标事件、HTTP 请求、文件读取)。
  • Observer — 消费者,订阅 Observable 并对三种事件做出响应:next(新值)、error(错误)、complete(流结束)。
  • Operators — 用于转换、过滤和组合数据流的纯函数(例如 map、filter、mergeMap)。


安装与配置



要在 Node.js 中使用 RxJS,请通过 npm 安装该包:



npm install rxjs


在文件中引入:



const { Observable } = require('rxjs');const { map, filter } = require('rxjs/operators');


创建 Observable



最简单的示例——创建一个数字流:



const { Observable } = require('rxjs');

const stream$ = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete();});

// 订阅stream$.subscribe({ next: value => console.log('收到:', value), error: err => console.error('错误:', err), complete: () => console.log('流已结束')});

// 输出:收到: 1, 收到: 2, 收到: 3, 流已结束


操作符:map 和 filter



操作符允许在不产生副作用的情况下处理流中的数据。过滤偶数并进行转换的示例:



const { of } = require('rxjs');const { map, filter } = require('rxjs/operators');

const numbers$ = of(1, 2, 3, 4, 5, 6);

numbers$.pipe( filter(x => x % 2 === 0), // 仅保留偶数 map(x => x * 10) // 乘以 10).subscribe(result => console.log(result));

// 输出:20, 40, 60


处理异步操作



RxJS 非常适合处理输入/输出事件。例如,使用 from 读取文件:



const { from } = require('rxjs');const { map } = require('rxjs/operators');const fs = require('fs');const path = require('path');

// 将文件读取封装为 Promiseconst readFilePromise = (filePath) => { return new Promise((resolve, reject) => { fs.readFile(filePath, 'utf8', (err, data) => { if (err) reject(err); else resolve(data); }); });};

// 从 Promise 创建 Observableconst fileStream$ = from(readFilePromise('./data.txt'));

fileStream$.pipe( map(content => content.toUpperCase())).subscribe({ next: data => console.log('文件内容:', data), error: err => console.error('读取错误:', err)});


组合数据流



RxJS 的一大优势是能够组合多个数据流。使用 merge(合并流)的示例:



const { interval, merge } = require('rxjs');const { take, map } = require('rxjs/operators');

// 流 A:每 1 秒一次const streamA$ = interval(1000).pipe( take(3), map(x => `A: ${x}`));

// 流 B:每 1.5 秒一次const streamB$ = interval(1500).pipe( take(3), map(x => `B: ${x}`));

// 合并

推荐