Rxjs 响应式编程库

来源:极链科技

作者:远卓

什么是Rxjs

RxJS是使用Observables 的响应式编程的库,它使编写异步或基于回调的代码更容易。随着深入你会发现它采用了订阅者模式,其中也带有纯函数的思想,比如Rxjs5中我们把“副作用”都写在.do()中。直到在使用了RxJS 6之后才了解其少有人意识到的另一面——流。

什么是流?node中的stream,gulp中的管道流... 这里我们不用专业术语来解释,用生活中大家熟悉的的例子来类比,比如“河流”。

河流有什么特点?至少有两个特点:水往低处流,河流虽然可能会蜿蜒盘旋,但是朝向固定,比如我国的长江和黄河就都是由西向东流。在RxJS中数据的流向也是固定的,就是从发送者到订阅者。基本都如下面这种形式:

河道有无数的分支也有无数的合并,在Rxjs中的是,通过不同的操作符将数据流拆分处理聚合又拆分。RxJS 6 相对于 RxJS 5(这里指5.5以下的版本,因为pipe函数在RxJS 5.5中作为新特性已被引入) 来说不仅修改了一部分操作符的名称,同时做了一个较大的改动,引入了管道(pipe)。

这种写法上的变化就带来了用法上的变化,以前的固定“河流”可以通过“管道”(pipe)来控制形成灵活的“水流”。

Rxjs vs Promise

Rxjs 和传统的Promise在处理异步问题上有什么差距呢?再代码层面什么是Rxjs说到底是要理解什么是Observable。RXJS是Observable的Javascript实现。

promise相较于Rxjs而言功能更单一 promise 只能将一个数据的状态由pending转换成resoloved或者rejected.而Rxjs可以处理多个数据对应complete和error状态但是Rxjs同时又拥有next方法。Observable是惰性的,需要subscribe的时候才输出值。promise内部状态是不可控制的,执行了就无法终止。而Observable可以定义如何取消异步方法。这也就是我下面会讨论到的一个异步场景。

输入框中输入字符,按回车发送一个请求,并将返回的结果变成一个todo item。如果在请求返回结果前又一次按下回车或add按钮,如果相同则不进行任何操作,如果不同则取消掉上次的请求并发送新的请求。(实际的场景往往是发送个http请求该请求会返回的很慢,业务上加上心跳检查,如果前一次在心跳间隔内无返回则再次调用请求,同时需要抛弃前一次请求的返回,并且此时有可能调用参数不一样的该接口从而造成数据不一致的问题)对于Promise实现我们不只要维护一个定时器timer 同时还要维护一个全局变量。

而Rxjs 我们可以通过switchMap 切换 Observable达到该效果

为什么使用 switchMap?

switchMap和其他打平操作符的主要区别是它具有取消效果。在每次发出时,会取消前一个内部 observable (你所提供函数的结果) 的订阅,然后订阅一个新的observable 。你可以通过短语切换成一个新的 observable来记忆它。

它能在像 typeaheads 这样的场景下完美使用,当有新的输入时便不再关心之前请求的响应结果。在内部observable长期存活可能会导致内存泄露的情况下,这也是一种安全的选择,例如,如果你使用mergeMap和interval,并忘记正确处理内部订阅。记住,switchMap 同一时间只维护一个内部订阅,在示例1中可以清楚出看到这一点。

不过要小心,在每个请求都需要完成的情况下,考虑写数据库,你可能要避免使用 switchMap。如果源observable发出速度足够快的话,switchMap可以取消请求。在这些场景中,mergeMap是正确的选择。

这里的switchMap其实是map and switch,而switch操作符的行为是:

如果Observable中流动的数据也是Observable,switch会将数据流中最新的一个 Observable订阅并将它的值传递给下一个操作符,然后取消订阅之前的 Observable。

简直就是为心跳检查量身定做。不管你异步的状态是怎么样switchMap中的Observable只订阅最新的一个。下面有个例子可以帮你很清晰的理解:

尝试一些场景中使用Rxjs

1.写一个基于 websocket 的在线聊天室,每次websocket收到新消息,不可能都立刻渲染出来,如果是用于生产,同时会有很多人说话wx渲染很大程度会有性能问题。用JS写的话,你需要维护一个数组,和一个timer,收到消息,先放进数组,然后timer负责把消息渲染出来,同时还要考虑清理timer,类似:

而在Rxjs中通过操作符bufferTime 就可以减少维护timer的成本:

比如我们需要监听页面滚动的事件,作出一些逻辑操作,这是就会产生事件过于频繁的调用,造成页面卡顿的现象。用原生js实现的时候,需要实现个节流或者防抖函数,通过实现个闭包函数,在内部维护个定时器。而在Rxjs中通过操作符debounce 就可以方便的解决

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20190402A0B4N000?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券