高阶:一个值映射成一条流,四种拍平策略
到 变换一页为止,map 的结果都是普通值。可一旦 map 的返回值本身又是一个 Observable——比如「每个搜索词映射成一次网络请求」——就得到一个高阶 Observable(流的流)。要拿到里面真正的值,必须把它
flatten 成一条流。问题是:内层的多条流在时间上会重叠,该怎么合并?RxJS 给出四种答案。
下面用同一条外层输入(三个查询 a / b / c 在不同时刻到达,每个映射成一条持续 3 拍的内层流),并排跑四种策略。拖动或播放时间游标,看四条下游 marble 如何分道扬镳。marble 的颜色标出它来自哪个查询。
1 · 四种策略,各自的取舍
| 策略 | 内层重叠时 | 并发 | 会取消 / 丢弃吗 | 典型用途 |
|---|---|---|---|---|
mergeMap |
全部并发 | 无上限 | 都不,全保留 | 独立并行任务 |
concatMap |
排队等待 | 1(串行) | 不丢,但会阻塞 | 严格保序 |
switchMap |
取消旧的 | 1(最新) | 取消旧内层 | autocomplete / 切换 |
exhaustMap |
忽略新的 | 1(最早) | 丢弃新值 | 防重复提交 |
为什么 autocomplete 要用 switchMap。 用户快速改动输入,每次改动都发一次请求。若用 mergeMap,旧请求的响应可能晚于新请求先返回,把过期结果显示出来——这就是请求竞态。switchMap
在新值到来时取消上一条内层订阅(触发它的 teardown、放弃在途请求),永远只保留最新那条。到 落地一页有可交互的完整 demo。