这是我参与 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其实就是发布者和订阅者之间玩的游戏
,可能你还是不理解,那我们再说的具体点。
- RxJS是一个事件的处理库,用于处理各种事件,比如DOM的点击、定时器的触发、API的消息获取
- 事件需要订阅,比如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的本质。