RxJS 主题概览
学习 RxJS 如何使用 Subjects 来处理多个生产者随着时间推移向多个消费者通过同一数据流推送值的情况。
在上一课中,我们学习了每个订阅者都会调用 Observable 的 subscribe 函数,这意味着每个订阅者都拥有该 Observable 的独立执行上下文。这种模式被称为 单播(unicast)值传递。
另一方面,有时我们需要一种不同的方式:让同一个 Observable 的执行上下文被所有订阅者共享。这种模式被称为 多播(multicast)值传递。
Subjects 是 RxJS 中一种特殊的 Observable 类型,能够实现 多播。
引入 Subjects
Subject 是 RxJS 中一种特殊的结构,它既可以作为 Observable,也可以作为 Observer。
- 你可以像订阅 Observable 一样订阅一个 Subject。
- 你可以通过调用
next方法向 Subject 推送值,这与在 Observable 的subscribe函数中推送值的方式相同。
任何感兴趣的订阅者只需简单地订阅 Subject,就可接收其产生的值,而无需关心这个 Observable 的执行上下文是为每个观察者独立创建的,还是被共享的。
每个数据生产者都可以随时间向 Subject 发布值,这些值会被多播给所有已订阅的观察者。
它是如何实现的?
Subject 会维护一个所有活跃订阅者的列表,当有新值到来时,这些值会在相同的执行上下文中被广播给每一个订阅者。
你可能会问:既然可以直接使用 Observable,那为什么还需要 Subjects 呢?
设想你的应用中有多个服务,它们会随时间产生数据。最好的做法是将这些数据发布到 Subject 中,这样数据就会被多播给所有订阅者,从而大大简化代码逻辑,减少重复工作。下图展示了这一工作流程。
Subjects 还提供了其他优势,我们将在后续课程中深入探讨。但目前,让我们专注于实现上图所示的示例代码。
1<html> 2 <head> 3 <script src="/main.js"></script> 4 </head> 5</html>
在上述实现中,每个消费者都订阅了 Subject,每个生产者也向 Subject 推送了一个值。注意,每个订阅者都能接收到每个生产者发布的值。这正是 Subjects 的强大之处。相比使用 Observable 实现相同功能,这段代码要简洁得多。
Subject 还有一个关键特性。你能在上面的例子中发现吗?如果没找到,可以尝试将第 35–37 行与第 39–41 行互换位置。这样可以让生产者在任何观察者注册之前就向 Subject 推送值。
注意输出为空。
这与 Subject 的“时间上的值”概念有关。这意味着,只要某个值被推送到 Subject,所有已注册的观察者都会收到它。但那些稍后才注册的观察者,将无法接收到之前发出的任何值。那么,如果我们希望新加入的观察者也能接收到部分历史值怎么办?RxJS 通过提供不同类型的 Subject 来解决这个问题,我们将在接下来的课程中详细探讨。
Subject 类型
RxJS 提供了多种 Subject 类型,适用于不同的使用场景。它们包括:
- Behavior Subject
- Async Subject
- Replay Subject
我们将逐一深入研究每种 Subject 类型,因为它们将在我们即将构建的项目中被广泛使用。
Quiz
在以下哪种场景中,你会选择使用 Subject 而不是 Observable?