RxJS 源代码学习 —— 概览

1,081 阅读3分钟

RxJS 是什么

依照 RxJS 的官方定义,

RxJS 是使用 Observables 的响应式编程的库,它使编写异步或基于回调的代码更容易。

针对 JavaScript 中的非阻塞行为(non-blocking manner),RxJS in Action(Deniels, P.P etc.)列举了 3 种处理方式,包括回调函数(callback functions)、事件派发器(Event Emitters)以及Promise。RxJS 则提出了一种新的思维方式:数据流,基于数据流来处理 JavaScript 中的异步或回调函数。举个例子,监听按钮点击事件,我们通常的处理方式是:

const button = document.querySelector('button');

button.addEventListener('click', () => {
    /** code **/
});

基于 RxJS 的处理方式是:

const button = document.querySelector('button');

const subscription = fromEvent(button, 'click').subscribe(() => {
    /** code **/
});

从表面上看,操作符fromEvent和函数addEventListener做一样的事,能够达到一样的效果,似乎看不出来 RxJS 的优势在何处?RxJS in Action 提到了一句话:

The concept of a stream can be applied to any data point that holds a value; this ranges from a single integer to bytes of data received from a remote HTTP call.

不管是鼠标点击、键盘输入、触摸手势,还是 HTTP 请求发送,乃至于简单的数字处理,RxJS 均将其视为数据流,通过对数据源的订阅和操作,处理异步任务。所谓万物皆可数据流,不外如是。如果你从未接触过 RxJS,可能无法体会到这句话的美妙之处,但等你熟练使用 RxJS 来编写自己的代码后,回过头来,相信你会有更深的理解。

接下来,我们进入正题,RxJS 源代码学习之路。RxJS 官方文档罗列了几个核心概念,分别是:

  • Observable (可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。
  • Observer (观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。
  • Subscription (订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。
  • Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 mapfilterconcatflatMap 等这样的操作符来处理集合。
  • Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。
  • Schedulers (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeoutrequestAnimationFrame 或其他。

除此之外,其源代码中还向外暴露了 UtilsNotification,具体内容我们会在后面的学习中慢慢接触到。接下来,我们首先来学习 RxJS 框架中核心的核心——Observable

代码调试

学习源代码,不可避免地需要调试源代码,帮助我们理解个中设计。第一步,从 Github 获取 RxJS 框架源代码:

$ git clone https://github.com/ReactiveX/rxjs.git

接下来,按照官方文档指示,执行第三方库安装 & 代码编译:

$ yarn install
$ yarn compile

到此,RxJS 本地库编译完毕,我们需要想办法将其引入到自己的测试项目中。我们可以通过一些基础的手段创建一个简单的测试项目:

$ mkdir rxjs-learning && cd rxjs-learning
$ npm init
$ yarn add typescript ts-mode
$ npx tsc --init # 创建 tsconfig.js
$ mkdir src && touch src/index.ts

而后,修改 package.json:

{
  "name": "rxjs-learning",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "playground": "./node_modules/.bin/ts-node src/index.ts"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "rxjs": "^7.1.0",
    "ts-node": "^10.0.0",
    "typescript": "^4.3.4"
  }
}

由此,我们可以通过运行:

yarn playground

来执行 src/index.ts 中的代码。如上,创建自定义测试项目的方法并不重要,重要的是我们需要将 RxJS 编译好的代码链接到自己的项目中,因此:

$ cd rxjs && yarn link

完成之后,打开自己的项目:

$ cd rxjs-learning && yarn link rxjs

至此,本地 RxJS 代码将会替代 ./node_modules/rxjs 运行,快来试试吧!接下来,我们将首先学习 RxJS 的 Obsevable 模块,参见 RxJS 源代码学习(二)—— Observable (juejin.cn)