我如何理解 RxJS
RxJS 是 JavaScript 实现的响应式扩展库的缩写。它内置于 Angular 中,也可单独使用。它实际上是对“响应式编程”模式的一种实现。因此,目前有多种不同语言的扩展库。RxJS 是一款非常强大的工具,尤其适用于那些你知道操作如何开始、如何结束,并且希望在中间进行更改的情况。
以下示例均使用 JavaScript 编写。但其通用概念应该适用于所有情况。我将要回顾的主要概念是可观察对象、订阅、观察者、管道和操作符。我们先从第一个开始。
可观察对象
可观察对象有很多名称,它也被称为流,甚至可观察流。但归根结底,可观察对象模式是一种将异步事件作为集合处理的方法。快速提醒一下,在编程中,我们经常希望以异步模式接收数据。发出调用来检索信息,并执行其他操作直到获得结果。可观察对象是处理这些调用和结果的一种方法。
在这篇文章的剩余部分,我将使用一个帮助我理解可观察模式的类比。假设一个可观察对象是一条河流。它本来可以承载船只(事件),但现在它不能,因为河的起点处有一座吊桥。
Observable 的独特之处在于它有两种模式:开启和关闭。Observable 默认处于关闭状态。因此,Stream 可以开启并载船,但现在它处于关闭状态。
const obs = of(1,2,3,4)
从一组项目创建可观察对象的运算符示例。
订阅
当我们订阅可观察对象时,它们就会被开启。这相当于升起吊桥,让船只顺着河流航行。我们也可以取消订阅,放下吊桥,关闭河流上的船只。
const obs = of(1,2,3,4)
obs.subscribe(observer)
请注意,可观察对象可以有多个订阅。但只需一个订阅即可“开启”我们的可观察对象。
观察者
假设我们需要一个人来升起吊桥。所以我们把这个人交给我们的订阅。这个人就是我们的观察员。这位观察员会观察河流,并报告每艘顺流而下的船只。
实际上,观察者是一个对象。观察者内部有三种可能的方法,但其中一种是必需的。它们是 next、error 和 complete。next 告诉可观察者如何处理发出的值。error 处理错误情况,而当没有更多值可发出时,则会调用 complete。
正是从这里我们开始理解拥有多个订阅者的价值。它们可以分别对可观察对象发出的值执行不同的操作。
例如,假设我们有红色和黄色的船。我们可以订阅可观察对象,观察器中的下一个方法可以只过滤掉红色的船,只有当用户看到红色的船时才会传递信息。我们也可以与另一个观察器进行另一个订阅,只处理黄色的船。
const obs = of(1,2,3,4)
const observer = {
next: (x) => console.log(x),
error: (err) => console.log(err),
complete: () => void
}
obs.subscribe(observer)
操作符和管道
现在,事情变得真正有趣了。操作符才是可观测领域真正的力量所在。想象一下,我们可以改变河流的流向,添加额外的景观特征和其他细节来改变我们的可观测源。请注意,我们不是直接改变船只,而是改变河流。我们添加了一片海洋,以便所有大型船只都流向那里,只有小型船只继续顺流而下。我们添加了一个涂成蓝色的瀑布,以便所有穿过它的船只都会变成蓝色。这些变化发生在河流本身(可观测源)上,当船只顺流而下时,它们也会受到影响。
我们可以将操作符串联起来。为此,我们使用管道。每个操作符接收一个可观察对象并返回一个新的。因此,无论我们使用多少个操作符,最终结果都是一个可观察对象。我们订阅该可观察对象,并将其应用于它之前的整个可观察对象链。因此,我们的观察者只会在船只经过所有操作符后,才会传递有关船只的信息。
const obs = of(1,2,3,4).pipe(
onlySmallBoats(),
paintBoatsBlue()
)
const observer = {
next: (x) => console.log(x)
}
obs.subscribe(observer)
实际上,这些将是真正的操作符,例如 map、combineLatest、race 等。
整合
如果我们将所有这些部分放在一起,我们的类比究竟解释了什么?
- 我们的可观察对象是一条河,河源头有一座吊桥,目前处于关闭状态
- 订阅正在升起那座吊桥
- 订阅已通过我们的观察员传递
- 我们只需要一个人来升起吊桥(一个订阅),但可以有很多
- 该人传递了有关它看到的顺流而下的船只的信息
- 我们可以让多个观察员观察我们的河流并传递有关不同船只子集的信息
- 河流可以具有充当操作者的物理特征,例如蓝色油漆瀑布,将经过的船只变成蓝色
- 您可以在河流上安排多个操作员,一个接一个地对它们进行管道连接,以便流经一个(输出)的船只将流经下一个(输入)
- 观察员将位于河流下游,位于最终操作员之后,并且仅传递当时有关船只的信息
- 取消订阅意味着我们放下吊桥,观察者回家
- 对于多个订阅,可观察对象将一直处于“开启”状态,直到没有剩余订阅,也就是当天最后一个观察者回家
- 当没有更多船只可看时,观察者可以回家(完成)
- 如果观察者看到的是一条龙而不是一艘船(一个错误),他们可能会觉得自己感觉不舒服,然后回家,不再观察船
就是这样。没有哪个比喻是完美的,但这个比喻有很多我很喜欢的地方。
结论
学习 RxJS 的很大一部分是学习具体的操作符。然而,人们在学习操作符时,经常只是复制粘贴代码,而没有真正理解其含义。RxJS 是一个强大的模式,而操作符实际上只是一个幌子,我们用它隐藏一堆复杂的回调函数。
记住,可观察对象并非万能。但它们能让之前棘手的问题变得简单得多。试试用它fromEvent
来查看表单字段的变化,这很酷!