RxJS 过滤运算符执行逻辑深度解析
核心概念概述
RxJS 是一个强大的响应式编程库,其核心在于 Observable(可观察对象)和操作符(Operators)的灵活组合。本文将深入解析 map
和 filter
运算符的执行过程,揭示 RxJS 数据流的处理机制。
示例代码分析
javascript
import { of, map, filter } from "rxjs";
const subscriber = of(1, 2, 3, 4, 5)
.pipe(map((val) => val * 3))
.pipe(filter((val) => val > 7))
.pipe(map((data) => data + 2));
subscriber.subscribe(console.log);
预期输出
11
14
17
执行流程详解
1. 创建阶段
of
操作符实现
javascript
function fromArrayLike(arrayLike) {
return new Observable((subscriber) => {
for (let i = 0; i < arrayLike.length; i++) {
subscriber.next(arrayLike[i]);
}
subscriber.complete();
});
}
- 创建一个 Observable 实例
- 接收数组形式的数据流
- 依次发送每个元素
- 最后发送完成通知
Observable 基础结构
javascript
export class Observable {
constructor(subscribe) {
if (subscribe) {
this._subscribe = subscribe;
}
}
// 惰性执行机制
subscribe(observerOrNext) {
const subscriber = new Subscriber(observerOrNext);
const teardown = this._subscribe(subscriber);
subscriber.add(teardown);
return subscriber;
}
pipe(...operations) {
return pipeFromArray(operations)(this);
}
}
关键特性:
- 惰性执行:只有在订阅时才真正执行
- 管道机制:支持操作符链式调用
2. 操作符实现原理
map
操作符
javascript
export function map(project) {
return source => {
return new Observable(function (subscriber) {
return source.subscribe({
...subscriber,
next: (value) => {
subscriber.next(project(value));
},
})
});
}
}
执行逻辑:
- 接收转换函数
project
- 返回一个接收源 Observable 的函数
- 创建一个新的 Observable
- 订阅源 Observable 并应用转换
filter
操作符
javascript
export function filter(predicate) {
return source => {
return new Observable(function (subscriber) {
return source.subscribe({
...subscriber,
next: (value) => {
predicate(value) && subscriber.next(value);
}
})
});
}
}
执行逻辑:
- 接收断言函数
predicate
- 返回一个接收源 Observable 的函数
- 创建一个新的 Observable
- 订阅源 Observable 并进行过滤
3. 执行流程分解
构建阶段
of(1,2,3,4,5)
创建初始 Observable- 每个
pipe()
调用都会:- 接收操作符函数
- 返回新的 Observable 实例
- 操作链形成但不执行
订阅阶段
- 调用
subscribe(console.log)
触发执行 - 执行顺序:
- 最外层的
map
订阅倒数第二层的filter
filter
订阅第一个map
- 第一个
map
订阅原始的of
Observable
- 最外层的
- 数据流处理:
of
发出原始值 (1,2,3,4,5)- 第一个
map
转换 (3,6,9,12,15) filter
过滤 (>7) → (9,12,15)- 最后
map
转换 (+2) → (11,14,17)
核心机制总结
- 惰性求值:只有订阅时才真正执行
- 操作符组合:每个操作符都返回新的 Observable
- 订阅链:形成从外到内的订阅关系
- 数据流处理:从源头依次通过各层操作符
可视化流程
scss
of(1,2,3,4,5) → map(x3) → filter(>7) → map(+2) → subscribe
↓ ↓ ↓ ↓
原始值 1,2,3,4,5 → 3,6,9,12,15 → 9,12,15 → 11,14,17
关键点提醒
- 每个
pipe()
都返回新的 Observable 实例 - 操作符通过闭包保存转换/过滤逻辑
- 订阅是从外向内建立的
- 数据流是从内向外传递的
...subscriber
保留了错误处理和完成通知的能力
理解这些机制有助于编写更高效、可维护的 RxJS 代码,并能够灵活组合各种操作符来处理复杂的数据流场景。