相应式编程-操作符号归类

总结操作符号归类:
映射与转换:map, flatMap, switchMap   → 用于数据格式转换与展开异步操作

过滤与节流:filter, debounceTime, throttleTime   → 用于控制事件频率与过滤无效数据

合并与组合:merge, zip, combineLatest   → 用于多流数据的合并和同步处理

累积与缓冲:scan, buffer, window   → 用于生成累积状态或批处理数据

错误处理与重试:catchError, retry   → 用于捕获错误、恢复及自动重试

辅助与调度:tap, delay, timeout   → 用于副作用操作、时序控制以及网络请求超时防护

  1. 映射与转换操作符
    1.1 map

    功能说明: 将来源流中的每一项转换为另一种数据类型或形态,相当于对每个元素进行函数映射。

    使用场景:

     数据格式转换:例如将网络请求返回的 JSON 数据转换成实体对象。
    
     UI 显示:将原始数据转换为视图模型或直接转成字符串供 UI 显示。
    

    示例代码(RxDart 风格):
    dart
    Copy

    stream.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));
  1. 过滤与节流操作符
    2.1 filter

    功能说明: 只让满足条件的数据项通过,过滤掉不符合条件的项。

    使用场景:

     用户输入校验:例如只处理非空、格式符合要求的输入事件。
    
     错误数据剔除:在数据流中丢弃那些无效或异常的数据。
    

    示例代码(RxDart 风格):
    dart
    Copy

    stream.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));
  1. 合并与组合操作符
    3.1 merge

    功能说明: 将多个 Observable 的数据流合并成一个 Observable,数据流不需要按顺序同步。

    使用场景:

     多源事件合并:将来自多个 UI 控件或接口的数据合并处理。
    
     并发响应:同时监听多个并发请求的返回,并统一处理结果。
    

    示例代码(RxDart 风格):
    dart
    Copy

    Observable.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));
  1. 累积与缓冲操作符
    4.1 scan

    功能说明: 类似于数组的 reduce 操作,但会逐步累积每一次的结果并发射中间状态。

    使用场景:

     状态管理:在处理连续事件时构建累积状态,如计数器、累计求和或复杂状态树更新。
    
     实时统计:计算流中数据的移动平均、累积总和、或历史记录。
    

    示例代码(RxJS 风格):
    javascript
    Copy

    clicks$.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`));
  1. 错误处理与重试操作符
    5.1 catchError

    功能说明: 捕获数据流中的错误,并允许返回一个备用的 Observable,从而避免整个流由于错误中断。

    使用场景:

     网络请求容错:当请求失败时返回默认数据或提示用户错误信息。
    
     局部错误恢复:在处理多个独立数据流时,确保单个流出错不会影响整体应用的响应。
    

    示例代码(RxDart 风格):
    dart
    Copy

    stream
    .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));
  1. 辅助与调度操作符
    6.1 do / tap

    功能说明: 用于在数据流中执行副作用操作(例如日志记录、对 UI 做一些更新)而不改变数据本身。

    使用场景:

     调试和日志:在关键数据流中打印调试信息。
    
     性能监控:记录数据处理的时间点或状态更新。
    

    示例代码(RxJS 风格):
    javascript
    Copy

    observable$.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)则为调试、监控和时序控制提供支持。
posted @ 2025-05-24 15:56  米太白  阅读(36)  评论(0)    收藏  举报