Web 平台 API / RxJS · 从 Observable 标准契约,到它解决的那些问题 待审核 7 页

RxJS · 从 Observable 标准契约,到它解决的那些问题

RxJS 常被当成「一大堆 operator」来记,内核却只有一个标准契约:Observable,一个可以脱离库、用十几行就手写出来的接口。subscribe(observer) 触发一个 producer,producer 通过 observer.next / error / complete 把值推出去,并返回一个 teardown 作为 Subscription 供取消。TC39 的 Observable proposal 与 WICG 的 DOM Observable 提案(EventTarget.when())要标准化的就是这个形状 —— 后者仍是实验特性,仅 Chromium 135+(2025-04)落地(核对于 2026-08)。

本系列从这个契约本身出发: 先把它放进 singular/plural × pull/push标准坐标系里,看清它和 function / Iterator / Promise 的分工; 再依次拆 创建 → 变换 (operator) → 组合 (高阶 flatten) → 共享 (hot/cold); 最后落到工程里真正要解决的问题 —— 取消陈旧请求、防抖 autocomplete、拖拽、重试。每页都用 marble diagram 单步观察流随时间的演化。

标准接口:Observable 到底是什么 contract · Observable / Observer / Subscription

契约:十几行手写一个 Observable

从零手写 Observablesubscribe 调用 producer,producer 用 observer 上的三个方法推值,返回的 teardown 就是 Subscription

four-kinds · 标准坐标系 2×2

坐标系:function / Iterator / Promise / Observable

把四种取值方式放进「单值 / 多值 × 拉 / 推」的 2×2 网格:单值加拉是 function,多值加拉是 Iterator,单值加推是 Promise,多值加推是 Observable。每格用能跑的代码演示各自的取值接口。

构造与变换:从值到流,再变形 creation · of / from / interval / timer / fromEvent

创建:把任何东西变成一条流

五个 creation function 把值、数组、Promise、定时器与 DOM 事件包成同一种 Observable。其中四个是 cold 的,fromEvent 惰性但 hot。

operators · pipe / map / filter / scan / take

变换:pipe 把 operator 串成管道

operator 是纯函数,吃一个 Observable 返回一个新的 Observable,从不改动上游;pipe(a, b, c) 只是函数组合。逐值看五个 operator 如何改写、丢弃或截断 marble。

组合与共享:多条流拧到一起 flattening · mergeMap / concatMap / switchMap / exhaustMap

展平:一个值映射成一条流,四种策略

map 的结果本身是 Observable 时得到高阶 Observable,需展平成一条流。内层重叠时保留谁,分出四种策略:全留、排队、留新、留旧。

hot-cold · Subject / share / multicast

冷与热:各跑一遍,还是共享一次执行

cold Observable 每个订阅者各触发一次独立执行;hot 流的值独立于订阅产生,多个订阅者共享同一次执行,晚订阅者错过之前的值。share 与 multicast 如何把 cold 转 hot。

解决哪些问题:落到真实工程 applications · 竞态 / 防抖 / 拖拽 / 重试

落地:这些问题,用流怎么解决

把前面的契约与 operator 对上真实痛点:autocomplete 的抖动与请求竞态、拖拽的三事件组合、失败后按退避重订阅。末尾一张「问题到 operator」的速查表。

一句话串起来

RxJS 的地基是一个标准契约 Observable —— 推送式、惰性、可取消的多值序列 (见 契约),它在 pull/push × 单值/多值 坐标系里正好补上 Promise 缺的那格 (见 坐标系)。有了契约就能把任何东西创建成 cold 流 (见 创建),用 pipe 里的纯函数 operator 变换 (见 变换);当值映射出的又是流,就用四种 flatten 组合 (见 高阶),用 Subject / share 决定是否共享执行 (见 冷与热)。这一切最终是为了优雅解决工程里的竞态、防抖、取消、重试 (见 落地)。

顺着标准与源头读下去

官方文档 / 教程

  • RxJS · Observable 指南 rxjs.dev 官方对 Observable / Observer / Subscription / Subject / operator 的权威说明,marble 与代码对照。
  • Learn RxJS learnrxjs.io 按 operator 分类的速查与配方,每条附可运行示例;查「该用哪个 operator」的好去处。
  • RxMarbles rxmarbles.com 可交互 marble diagram:拖动源 marble 实时看各 operator 的输出,本系列可视化的灵感来源。

标准接口的源头

  • TC39 · Observable proposal github.com 把 Observable 纳入 ECMAScript 的提案,定义了 subscribe / Observer / Subscription 的最小契约。
  • WICG · Observable (DOM) 提案 github.com 把 Observable 引入 DOM 的提案本体:EventTarget.when() 直接返回事件的 Observable,相当于原生的 fromEvent。仅 Chromium 系落地。
  • MDN · Streams API developer.mozilla.org 对照另一套「流」抽象:ReadableStream 是 pull-based + backpressure,与 Observable 的 push 模型形成互补。