<ijse blog />

RxJS 入门记录

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

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

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

问题

以下是我们在处理数据层时希望能够被解决好的问题:
  • 异步的数据源
  • 多种数据关联计算
  • 需要最小范围更新(精准更新)
  • 定时触发更新
一个较理想的方式:我们把数据抽象包装为数据线,然后像接线一样将不同数据线连接到我们的处理模块及控制器上;当数据线上有数据通过时,直接推送到我们数据消费方,或者经过控制器,有选择地推送。

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

准备

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

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

V4 vs V5

GitHub中主要有两个RxJS版本实现,分别是:
  • V4: https://github.com/Reactive-Extensions/RxJS
  • V5:https://github.com/ReactiveX/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上去找。