漫谈RxJS之基础概念篇

670 阅读3分钟

这是我参与 8 月更文挑战的第 28 天,活动详情查看: 8月更文挑战

前言

我们要谈及RxJS,不得不先说下Reactive Extensions(Rx),这是一种编程模式,他的目标是对异步的集合进行操作(ps: 这种编辑模式有利有弊,当然这不是本文的重点,这里不再赘述,有兴趣的同学可以自行查阅相关资料。)。Rx家族成员很多,如RxCpp、RxJava、Rx.NET、Rx.rb、RxPy等,我们从命名上不难看出,后缀就是语言的名称,那么就不难理解RxJS是Javascript语言对Reactive Extensions(Rx)的实现。

RxJS是什么?

引自官方文档的概念:

RxJS 是一个库,它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和受 [Array#extras] 启发的操作符 (map、filter、reduce、every, 等等),这些数组操作符可以把异步事件作为集合来处理。

可以把 RxJS 当做是用来处理事件的 Lodash

官方文档引入了很多概念,如Observer、 Schedulers、 Subjects,这些对初学者并不友好,因为这些都是RxJS的概念。RxJS的学习路线对于大多数人来说都太陡峭了,很容易从入门到放弃,甚至还没入门就放弃了。

我们把概念做个精简,RxJS其实就是发布者和订阅者之间玩的游戏

在设计模式中,有一个模式就是发布订阅模式,这个模式中,

  • 发布者只负责事件的通知
  • 订阅者只负责接收到通知后完成自身的业务逻辑,而并不关心消息的来源

大家都责任都很明确,但是必然有一些负责的情况,比如广播是私有的还是公开的,如果订阅者迟到了,那么前面的消息是否需要告知订阅者,对着这些情况的处理,RxJS定义了一套完整的操作符,注意是完整的,这个世界上所有的情况都被涵盖在操作符中了,你不必再造轮子了。

解决了什么问题?

上文说到RxJS其实就是发布者和订阅者之间玩的游戏,可能你还是不理解,那我们再说的具体点。

  1. RxJS是一个事件的处理库,用于处理各种事件,比如DOM的点击、定时器的触发、API的消息获取
  2. 事件需要订阅,比如DOM的点击通过addEventListener,API获取通过注册回调函数

通过两个步骤,我们成功划分出了发布者和订阅者,但是在实际业务场景中,这些事件的订阅和发布会更加复杂,涉及一对多、多对一、多对多等场景。

而异步事件的处理则更加复杂,相信很多人都听说过回掉地狱这个词,指的是在没有promise前,API的订阅需要用回调函数进行注册,一旦API有串行请求,就很容易写出冲击波代码,像这样:

    function getList() {
        request('url', {
            succcess: function(res) {
                request('url', {
                    data: res,
                    succcess: function(res) {
                        request('url', {
                            data: res,
                            succcess: function(res) {
                                // TODO
                            }
                        })
                    }
                })
            }
        })
    }

在promise成为规范后,后面async await这种用同步写异步代码的方式流行后,这种情况得到了改善,但是在RxJS中,你会看到一个不一样的编码方式,毕竟promise也属于另一个编程范式。

import { ajax } from 'rxjs/ajax';
import { concatMap } from 'rxjs/operators';

/* 1. 判断登录
 * 2. 获取基础信息
 * 3. 根据基础信息换取商品信息
 */
const order$ = ajax('url') // 1. 判断登录
  .pipe(
    concatMap(isLogin => ajax('url')), // 2. 获取基础信息
    concatMap(info => ajax('url')), // 3. 根据基础信息换取商品信息
  )
  .subscribe(goods => {
      // TODO
  });

小结

本章大概阐述了RxJS的一些基础概念,以及能帮我们解决什么问题,在下篇文章中,我们将结合实际业务场景,深入剖析RxJS的本质。