学习 RxJS 最大的问题是官方造了不少概念,但文档又解释得不太全面和易懂,须要结合阅读各类文章(特别是 Ben Lesh 的,包括视频)。本文试图总体梳理一遍再用另外的角度来介绍,但愿能帮助初学者或者对 RxJS 的一些概念比较含糊的使用者。javascript
做者最近作了一个无缝结合 React 与 RxJS 的库 observable-hooks,欢迎使用和星星🌟!
RxJS 属于响应式编程,其思想是将时间看做数组,随着时间发生的事件被看做是数组的项,而后以操做数组的方式变换事件。其强大的地方在于站在四维的角度看问题,这就像是拥有了上帝视野。html
在处理事件之间的关系时,对于传统方式,咱们须要设置各类状态变量来记录这些关系,好比对点击 Shift
键进行计数,须要手动设置一个 let shiftPressCount: number
,若是须要每 600ms 清零,又须要添加计时的状态,这些状态都须要手动维护,当它们变得复杂和庞大的时候咱们很快就会乱了,由于没有明确的方向,很差判断这些状态同步了没有。java
而这正是 RxJS 发光发热的地方。由于从四维的角度看,这些状态就不是单个变量,而是一系列变量。好比对按键计数:react
Rx.Observable.fromEvent(document, 'keydown') .filter(({ key }) => key === 'Shift') .scan(count => count + 1, 0) .subscribe(count => console.log(`按了 ${count} 遍 Shift 键`))
相信有使用过数组方法的人第一次看也大概能知道这里干了些什么(把 scan
看做是会输出中间结果的 reduce
)。中间状态都在变换的过程当中被封装起来,每一次事件的 count
都是独立的,不容易乱,也使得能够用纯函数去表达状态的变换。链式调用(或者 RxJS5 的 pipeable)在必定程度上限制了状态数据的流动方向,增长了可预测性,更加容易理解。git
使用 RxJS 前先理解它要作什么,这里引入了两个概念,Producer (生产者)和 Observer (观察者)。es6
先看一个熟悉的例子:github
document.addEventListener('click', function handler (e) { console.log(e.clientX) })
这里的 Producer 是 DOM 事件机制,会不按期产出 MouseEvent 事件。Observer 就是 handler
,对事件做出反应。编程
再看前面的例子:api
Rx.Observable.fromEvent(document, 'keydown') .filter(({ key }) => key === 'Shift') .scan(count => count + 1, 0) .subscribe(count => console.log(`按了 ${count} 遍 Shift 键`))
Producer 仍是 DOM 事件机制,Observer 是 subscribe
的参数。因此能够理解 RxJS 为链接 Producer 和 Observer 的纽带。数组
因而这个纽带的成分叫 Observable (可被观察的)就不难理解了。Observable 就是由事件组成的四次元数组。RxJS 将 Producer 转换为 Observable,而后对 Observable 进行各类变换,最后再交给 Observer。
对 Observable 进行变换的操做符叫作 Operator,好比上面的 filter
和 scan
,它们输入 Observable 再输出新的 Observable。RxJS 有巨量的 Operators ,这也是学习 RxJS 的第二难点,我已经分类整理了六十多个,整理完会再写一篇文章介绍,敬请关注。
RxJS 封装了许多有用的方法来将 Producer 转换为 Observable,好比 fromEvent
、fromPromise
,但其根本是一个叫 create
的方法。
var observable = Rx.Observable.create(observer => { observer.next(0) observer.next(1) observer.next(2) setTimeout(() => { observer.next(3) observer.complete() }, 1000) })
这其实跟 Promise 的思路很像,Promise 只能 resolve
一遍,但这里能够 observer.next
不少个值(事件),最后还能 complete(不是必须的,能够有无限事件)。官方把这个类 resolve
的参数也叫作 observer
,由于 observer.next(0)
的意思是“Subscribe 个人那个 Observer 接下来会得到这个值 0
”。我认为这是一个很差的决定,重名对于新人太容易混淆了,这个其实能够从另外一个角度看,把它叫作 producer,“产生”了下个值。
一个常见的误解是认为 RxJS 就是 addEventListener
那样的订阅者模式,subscribe
这个方法名也颇有误导性。然而二者并非一回事,订阅者模式会维护一个订阅者列表,事件来了就一一调用列表上的每一个订阅者传递通知。但 RxJS 并无这么一个列表,它就是一个函数,能够跟 Promise 类比,Promise 的 executor 是在 new Promise(executor)
时立刻执行的,而 RxJS Rx.Observable.create(observer)
的 observer
则是在每次执行 subscribe
后都调用一遍,即每次 subscribe
的 Observables 都是独立的,都会从新走一遍整个流程。
这个时候你也许会想,这样每次都完整调用一遍岂不是很浪费性能?没错,若是须要屡次 subscribe 同个 Producer 这么作会比较浪费,但若是只是 subscribe 一遍,维护一个订阅者列表也没有必要。因此 RxJS 引入了 Hot 和 Cold Observable 的概念。
Observable 冷热概念其实就是看 Producer 的建立受不受 RxJS 控制。
前面咱们知道,create
会将 Producer 转化为 Observable 。若是这个 Producer 也是在 create
回调里面产生的,那么就是 Cold ,由于 Producer 还不存在,只有 subscribe
了以后才会被建立。
但若是 Producer 在以前就建立了,好比 DOM 事件,create
回调里仅仅是对 Producer 添加 listener,那么这就叫作 Hot ,由于不须要 subscribe
来启动 Producer 。
只有 Hot Observable 才能够实现订阅者模式。能够经过一个特殊的 Observable 叫 Subject 来建立,其内部会维护一个订阅者列表。经过 share
方法能够将一个 Cold 的 Observable 转换为 Hot 。原理是内部用 Subject subscribe 上流的 Observable 实现转接。
理解了基本概念以后就能够直接开写了,自己没有什么魔法,参考一下 api 依样画葫芦便可。
使用 RxJS 最多见的问题是不知道何时该用哪一个 Operator 。这其实跟数组操做是同样的,RxJS 提供了数量庞大的 Operators ,基本覆盖了各类能够想到的数组操做,建议先从 JavaScript 常见的数组操做开始,如 map
、filter
、scan
(也有 reduce
,但这个一般不是咱们想要的,咱们通常不须要在 complete 以后才输出结果,而是每次都输出阶段性的结果)。
多翻官方文档,经常使用的 Operators 都描述得很是详细,有弹珠图(Marble Graph)和一句话总结;缺点是措辞有时可能会比较抽象,不是那么好理解。
更新:新的社区维护的 官方文档已经作得很是不错,推荐使用。
另外就是第三方的 learnrxjs 和 Rxjs 5 ultimate,按做者的思路组织,更通俗易懂些,能够做为补充理解;缺点是可能跟官方不一样步,以及不全。
我整理完也会再写一篇文章介绍,敬请期待。