RxJS 入门记录

最近项目由于业务复杂度的不断提升,前端页面的数据层管理有些混乱和低效,出现数据更新同步复杂,数据源众多等问题。

vuex 对于一般复杂的前端组件共享数据是没什么问题的,但是当后端数据源复杂,数据需要进行复杂的合并、关联计算、预处理时,mutation 和 action 就会写得愈加复杂,同时团队成员也可能由于水平问题及对业务的不同角度理解,容易造成数据层混乱,使接下来新业务功能的开发越来越复杂,代码慢慢变得维护困难。

在这种背景下,似乎 RxJS 是不错的解决方案。

问题


以下是我们在处理数据层时希望能够被解决好的问题:


  • 异步的数据源

  • 多种数据关联计算

  • 需要最小范围更新(精准更新)

  • 定时触发更新


一个较理想的方式:我们把数据抽象包装为数据线,然后像接线一样将不同数据线连接到我们的处理模块及控制器上;当数据线上有数据通过时,直接推送到我们数据消费方,或者经过控制器,有选择地推送。

这其实就是消息订阅,是观察者模式的一种实现。

准备


官网:http://reactivex.io/rxjs

Dash Docset: https://github.com/royling/rxjs.docset

V4 vs V5


GitHub中主要有两个RxJS版本实现,分别是:




V5是最新的版本,二者在思想方面是一致的,V5版本主要优点是:


  • 性能更好

  • 调用堆栈输出更简洁,更易于调试


详细对比:https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md

所以,现在更倾向使用V5版本。

使用npm安装RxJS 5: npm install rxjs

梳理

RxJS提供了各种API来创建数据流:


  • 单值:of, empty, never

  • 多值:from

  • 定时:interval, timer

  • 从事件创建:fromEvent

  • 从Promise创建:fromPromise

  • 自定义创建:create


创建出来的数据流是一种可观察的序列,可以被订阅,也可以被用来做一些转换操作,比如:


  • 改变数据形态:map, mapTo, pluck

  • 过滤一些值:filter, skip, first, last, take

  • 时间轴上的操作:delay, timeout, throttle, debounce, audit, bufferTime

  • 累加:reduce, scan

  • 异常处理:throw, catch, retry, finally

  • 条件执行:takeUntil, delayWhen, retryWhen, subscribeOn, ObserveOn

  • 转接:switch


也可以对若干个数据流进行组合:


  • concat,保持原来的序列顺序连接两个数据流

  • merge,合并序列

  • race,预设条件为其中一个数据流完成

  • forkJoin,预设条件为所有数据流都完成

  • zip,取各来源数据流最后一个值合并为对象

  • combineLatest,取各来源数据流最后一个值合并为数组


(from: https://github.com/xufei/blog/issues/44)
上面只是举例,实际RxJS提供了非常多的方法。

这里有一个非常棒的在线工具,将每个方法(operator)用marbles图画演示出来:


http://rxmarbles.com/

调试


在Devtools中调试异步代码通常都比较痛苦,目前可能最有效的方法仍是console.log:

添加<code class="highlighter-rouge">.do(x =&gt; console.log(x))在合适的结点。

另外, 还可以自己画流程图 或者 珠宝图。方法都比较原始,可能在阅读和调试别人的RxJS代码时仍会比较麻烦吧。

参考:https://staltz.com/how-to-debug-rxjs-code.html

> 有一个在线可视化调试工具:http://jaredforsyth.com/rxvision/,可惜作者已经不怎么维护了,并且它并不支持最新的RxJS V5版本。

资源


官网的Manual就是非常不错的入门教程:http://reactivex.io/rxjs/manual/overview.html

另外,其它一些资源可以从awesome-rxjs上去找。