RxJS 是一个流行的 JavaScript 库,用于响应式编程。它提供了处理异步事件流的方式,并可用于前端开发的各种问题解决方案中。在使用 RxJS 时,了解冷 Observable 和热 Observable 的差异是非常重要的,因为它们在处理流时有很大的不同。
什么是 Observable?
Observable 是 RxJS 中的一个对象,它表示异步事件流的概念。事件流可以是来自任何源的数据,例如用户交互、网络请求和计时器。Observable 实例是可被订阅的,因此当事件发生时,可以通过 Observer 来执行某些操作。
Observer
Observer 是一个对象,它定义了如何响应 Observable 发出的值。当 Observable 触发事件时,Observer 可以执行一些功能,例如将事件打印到控制台,显示动画或更改 DOM 中的元素。
Observer 必须实现三个方法:
- next(value) - 当 Observable 发出一个值时,会调用此方法。
- error(err) - 当 Observable 发生错误时,可以通过此方法处理该错误。
- complete() - 当 Observable 完成时,该方法被调用。
冷 Observable
冷 Observable 是最容易理解的一种,当你订阅它时,Observable 会为每个 Subscriber 重新执行一遍。因此,对于每个新的订阅者,Observable 都会重新执行并生成事件流。这就是“冷”的含义,因为它为每个订阅者提供了一个新的事件流。
例如,下面的代码中,我们创建一个简单的冷 Observable:
------ - ---------- - ---- ------- ----- ---------- - --- --------------------- -- - ----------------------- -- --------------- ----------------- ----------------- ----------------- --- ---------------------------- -- ----------------------- -- ------------ ---------------------------- -- ----------------------- -- ------------
这会输出:
---------- -- ------------ ---------- -- - ---------- -- - ---------- -- - ---------- -- ------------ ---------- -- - ---------- -- - ---------- -- -
这表明了,对于每个订阅者,Observable 都重新执行并生成一个新的事件流。
热 Observable
热 Observable 区别于冷 Observable 的最大不同点是,它会在 Observable 创建后立即开始发出事件,即无论是否有已订阅的观察者。这就是“热”观察者的含义,因为它始终发出同一个事件流。
例如,下面的代码中,我们创建了一个热 Observable:
------ - --------- - ---- ------- ----- ----- - ------------------------ --------- ------------------ -- ----------------------- - ------------ ------------- -- - ------------------ -- ----------------------- - ------------ -- ------
此代码会在页面中的任何位置监听用户单击事件。如果用户在两秒内单击两次,那么两个不同的订阅者都将获得该事件,因为该事件流已经存在并且正在发出通知。
解决方案:主题和 ReplaySubject
如果你希望通过订阅一个 Observable,仅能获取数据的最新更新(而不是发出的每个更新),那么你需要使用 RxJS 中的 Subject。
主题(Subject)
Subject 可以像 Observable 一样发出值,并且还可以通过 next() 方法将新值传递给已订阅的观察者。Subject 还充当观察者和被观察者之间的桥梁,也就是说,它既可以订阅 Observable,还可以被其他观察者订阅。
Subject 有两种类型:普通(或非广播)和广播。我们可以使用普通主题来解决热观察者的问题。普通主题在创建时不会发出任何值,而只有在绑定的 Subscriber 收到任何值时才会发出它们。这种方式可以确保每个订阅者获取到有用的更新,但是,如果订阅普通主题的其他 Subscriber 发生在最新更新之前,订阅者将无法获得该更新。
例如:
------ - ------- - ---- ------- ----- ------- - --- ---------- ---------------- ------------------------- -- ----------------------- -- ------------ ---------------- ---------------- ------------------------- -- ----------------------- -- ------------ ----------------
输出:
---------- -- - ---------- -- - ---------- -- - ---------- -- - ---------- -- -
ReplaySubject
ReplaySubject 是一种可重播的 Subject,在订阅之前会记录 Observable 发出的最新 n 个项,并在订阅后将这些项发出。这使您可以在订阅 Replaysubject 的新 Subscriber 时,让它们接收到最新和以前的所有更新。例如:
------ - ------------- - ---- ------- ----- ------- - --- ----------------- ---------------- ---------------- ---------------- ------------------------- -- ----------------------- -- ------------ ---------------- ------------------------- -- ----------------------- -- ------------ ----------------
输出:
---------- -- - ---------- -- - ---------- -- - ---------- -- - ---------- -- - ---------- -- - ---------- -- -
在上面的示例中,我们创建了一个新的 ReplaySubject,它保存最新的两个值。我们首先将值 1、2 和 3 发送到 ReplaySubject 中。然后,我们订阅了 ReplaySubject,这会向订阅者 A 发出最新的两个值(即 2 和 3)。接下来,我们发送了值 4,并订阅了 ReplaySubject,这会要求订阅者 B 获取最新的两个值,这是值 3 和 4。最后,我们发送值 5,并将其发送给两个订阅者。这是主题的适当的行为形式,因为每个 Subscriber 都会获得相同的值。
结论
熟悉 RxJS 中的冷 / 热 Observable 差异以及如何解决这些差异的问题,可以帮助您更好地处理异步事件流,编写更高效的代码以及提高代码可读性。概括而言,使用普通主题或 ReplaySubject 通过订阅 Observable 来确保每个新订阅者都能获取到有用的更新,并且能够获得最新的值。如果您需要更精细的控制,则可以从热 Observable 转移到 Subject 或 ConnectableObservable。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6707cd7ed91dce0dc86c9c91