坐标系:function / Iterator / Promise / Observable
JavaScript 里「拿到一个值」的方式,可以放进一张 2×2 的坐标系:一个轴是值的个数(singular 单值 / plural 多值),另一个轴是谁主导取值(pull 消费者主动拉 / push 生产者主动推)。四个格子,恰好对上四种熟悉的接口。Observable
不是凭空冒出来的新概念,它填的正是右下角那格——多值 + push。
点下面网格里的任意一格,右侧用能跑的代码演示它的取值方式。默认停在 Observable 这格:它是 Promise 在「多值」维度上的自然推广,也是 TC39 Observable proposal 与 WHATWG DOM
Observable(el.when('click'))想标准化的形状。
1 · 四者放在一起对照
同一张坐标系换个角度看:决定一个接口落在哪一格的,就是下面这四个属性。pull 一列由消费者掌握节奏(你调用才有值);push 一列由生产者掌握节奏(值就绪了推给你)。从上到下,值的个数从一个变成任意多个。
| 接口 | 求值时机 | 值的个数 | 谁主导 | 能否取消 |
|---|---|---|---|---|
| function | 同步,调用即返回 | 单值 | 消费者拉(pull) | —(瞬时完成) |
| Iterator | 同步,逐个惰性求值 | 多值 | 消费者拉(pull) | 停止 next() 即可 |
| Promise | 异步,就绪后一次 | 单值 | 生产者推(push) | 不能取消 |
| Observable | 异步,随时间陆续 | 多值 | 生产者推(push) | unsubscribe 取消 |
Observable = 多值版的 Promise。 Promise 在「push」这一列,但只 resolve 一个值;把「单值」放宽成「多值」,同一列往下走一格,得到的正是 Observable——一个能随时间推任意多个值、并且可取消的生产者。它为什么惰性、如何用
next / error / complete 推值、怎样 unsubscribe 收尾,见 契约;怎样把 DOM 事件、定时器、Promise 包成 Observable,见 创建。