相应式编程-操作符号归类
总结操作符号归类:
映射与转换:map, flatMap, switchMap → 用于数据格式转换与展开异步操作
过滤与节流:filter, debounceTime, throttleTime → 用于控制事件频率与过滤无效数据
合并与组合:merge, zip, combineLatest → 用于多流数据的合并和同步处理
累积与缓冲:scan, buffer, window → 用于生成累积状态或批处理数据
错误处理与重试:catchError, retry → 用于捕获错误、恢复及自动重试
辅助与调度:tap, delay, timeout → 用于副作用操作、时序控制以及网络请求超时防护
-
映射与转换操作符
1.1 map功能说明: 将来源流中的每一项转换为另一种数据类型或形态,相当于对每个元素进行函数映射。
使用场景:
数据格式转换:例如将网络请求返回的 JSON 数据转换成实体对象。 UI 显示:将原始数据转换为视图模型或直接转成字符串供 UI 显示。示例代码(RxDart 风格):
dart
Copystream.map((item) => ItemModel.fromJson(item));
1.2 flatMap / mergeMap
功能说明: 处理那些映射函数返回的是一个新的 Observable(数据流)的情况,将多个内部流合并到主流中。
使用场景:
网络请求链:例如,从一个用户输入流中采集搜索关键词,然后为每个关键词发起异步 API 请求,合并所有请求结果。
动态异步任务:根据某个事件触发另一系列异步操作,且这些操作的结果不必按原顺序返回。
示例代码(RxJS 风格):
javascript
Copy
input$.pipe(
flatMap(query => ajax.getJSON(`/api/search?q=${query}`))
).subscribe(results => updateUI(results));
1.3 switchMap
功能说明: 类似于 flatMap,但每当有新事件触发时,会取消上一次未完成的内部流,只处理最新的任务。
使用场景:
实时搜索建议:当用户输入时,每次输入变化发起的搜索请求,只在最后一次输入停顿后返回结果,从而避免处理“过时”的查询。
切换数据源:用于 UI 中的 Tab 切换或动态数据请求,每次切换时只关注当前激活项的数据。
示例代码(RxJS 风格):
javascript
Copy
input$.pipe(
switchMap(query => ajax.getJSON(`/api/search?q=${query}`))
).subscribe(results => updateUI(results));
-
过滤与节流操作符
2.1 filter功能说明: 只让满足条件的数据项通过,过滤掉不符合条件的项。
使用场景:
用户输入校验:例如只处理非空、格式符合要求的输入事件。 错误数据剔除:在数据流中丢弃那些无效或异常的数据。示例代码(RxDart 风格):
dart
Copystream.where((input) => input.isNotEmpty);
2.2 debounceTime
功能说明: 当源 Observable 发出数据后等待指定的时间,如果在这段时间内没有新的数据发出,则发出该数据。常用于防抖处理。
使用场景:
输入防抖:避免在短时间内连续触发搜索请求,只有用户停止输入后再执行查询。
按键事件:对连续点击做防抖,确保只处理最后一次点击或在停止点击后的动作。
示例代码(RxJS 风格):
javascript
Copy
input$.pipe(
debounceTime(300)
).subscribe(value => performSearch(value));
2.3 throttleTime
功能说明: 限制数据流中事件在一定时间内只允许发出一次,适用于控制高频事件。
使用场景:
滚动监听:防止滚动或窗口调整事件处理过于频繁,影响性能。
传感器数据:采集传感器数据时避免过高数据量;例如,将连续的陀螺仪数据减少后再处理。
示例代码(RxJS 风格):
javascript
Copy
scrollEvent$.pipe(
throttleTime(200)
).subscribe(event => updateScrollPosition(event));
-
合并与组合操作符
3.1 merge功能说明: 将多个 Observable 的数据流合并成一个 Observable,数据流不需要按顺序同步。
使用场景:
多源事件合并:将来自多个 UI 控件或接口的数据合并处理。 并发响应:同时监听多个并发请求的返回,并统一处理结果。示例代码(RxDart 风格):
dart
CopyObservable.merge([stream1, stream2, stream3])
.listen((item) => handleItem(item));
3.2 zip
功能说明: 同步地组合多个 Observable,将各自按顺序对应的数值打包成一个数组或对象。
使用场景:
关联数据:例如当你有两个独立的 API 调用,且其中一项的数据必须与另一项的数据一一对应时使用。
分组数据处理:合并来自不同数据源的行数据,形成完整的记录。
示例代码(RxJS 风格):
javascript
Copy
zip(api1$, api2$).subscribe(([result1, result2]) => {
processCombined(result1, result2);
});
3.3 combineLatest
功能说明: 当任一被组合的 Observable 发出新的数据时,将所有 Observable 的最新数据合并后发出。
使用场景:
表单数据联动:例如多个输入框的数据变化时,根据各自当前的最新值更新一个预览或汇总信息。
多数据依赖:当多个数据源都可能独立变化,而 UI 又需要最新的全部数据更新时使用。
示例代码(RxDart 风格):
dart
Copy
Rx.combineLatest2(stream1, stream2, (a, b) => CombinedModel(a, b))
.listen((combined) => updateUI(combined));
-
累积与缓冲操作符
4.1 scan功能说明: 类似于数组的 reduce 操作,但会逐步累积每一次的结果并发射中间状态。
使用场景:
状态管理:在处理连续事件时构建累积状态,如计数器、累计求和或复杂状态树更新。 实时统计:计算流中数据的移动平均、累积总和、或历史记录。示例代码(RxJS 风格):
javascript
Copyclicks$.pipe(
scan((total, click) => total + 1, 0)
).subscribe(count => console.log(Clicked ${count} times));
4.2 buffer & window
buffer
功能说明: 收集源 Observable 在一定时间段或一定数量内的所有数据,并作为一个数组一次性发出。
使用场景:
批量处理:例如,在高频鼠标移动事件中收集一段时间内的数据,批量处理后再更新 UI,以降低渲染频率。
数据打包上传:在网络不稳定时,将数据临时缓存起来,当条件满足后一次性发送到服务器。
window
功能说明: 将数据流按时间或数量分窗,每个窗口是一个内部 Observable,后续可以对窗口内的数据再进行处理。
使用场景:
实时数据分段:例如,实时图表中每隔一定时间更新一个图形的局部数据。
维护动态分组:在时间窗口内统计事件频率,动态生成报告。
示例代码(RxJS 中 bufferTime 示例):
javascript
Copy
events$.pipe(
bufferTime(1000)
).subscribe(events => console.log(`Received batch of ${events.length} events`));
-
错误处理与重试操作符
5.1 catchError功能说明: 捕获数据流中的错误,并允许返回一个备用的 Observable,从而避免整个流由于错误中断。
使用场景:
网络请求容错:当请求失败时返回默认数据或提示用户错误信息。 局部错误恢复:在处理多个独立数据流时,确保单个流出错不会影响整体应用的响应。示例代码(RxDart 风格):
dart
Copystream
.catchError((error) => Stream.value(defaultValue))
.listen((data) => updateUI(data));
5.2 retry
功能说明: 当检测到错误时自动重试订阅源,可以指定重试次数。
使用场景:
短暂网络问题:当网络请求偶尔失败时,自动重试可以提升用户体验。
不稳定数据源:在数据读取过程中,遇到暂时问题时进行多次尝试。
示例代码(RxJS 风格):
javascript
Copy
ajax.getJSON(url).pipe(
retry(3)
).subscribe(data => render(data), error => console.error(error));
-
辅助与调度操作符
6.1 do / tap功能说明: 用于在数据流中执行副作用操作(例如日志记录、对 UI 做一些更新)而不改变数据本身。
使用场景:
调试和日志:在关键数据流中打印调试信息。 性能监控:记录数据处理的时间点或状态更新。示例代码(RxJS 风格):
javascript
Copyobservable$.pipe(
tap(value => console.log("当前值:", value))
).subscribe();
6.2 delay / timeout
delay
功能说明:对每一项数据延迟一段时间再发出。
使用场景:
模拟网络延时:测试 UI 在延迟情况下的响应。
顺序控制:在多步任务中为了确保时序正确而延迟后续处理。
timeout
功能说明:若在指定时间内没有收到数据,则抛出错误或切换到备用数据流。
使用场景:
保护性措施:防止长时间等待数据(如网络请求超时),及时反馈错误或进行重试。
示例代码(RxJS 风格):
javascript
Copy
observable$.pipe(
timeout(5000)
).subscribe(data => console.log(data), error => console.error('Timeout!', error));
小结
响应式编程操作符为复杂的数据流控制提供了丰富的工具:
映射与转换(map、flatMap、switchMap)用于将数据转变并发起新的异步操作;
过滤与节流(filter、debounceTime、throttleTime)帮助控制事件频率和内容;
合并与组合(merge、zip、combineLatest)使多路数据流的协同工作变得简单;
累积与缓冲(scan、buffer、window)适合对事件进行分组、统计和状态累加;
错误处理与重试(catchError、retry)确保系统在面对故障时依然平稳运行;
辅助操作符(tap、delay、timeout)则为调试、监控和时序控制提供支持。
浙公网安备 33010602011771号