RxJS 中各种 Subject 类型的比较
RxJS 提供了多种 Subject 变体,每种都有不同的特性。以下是主要的 Subject 类型及其比较:
1. Subject
基本特性:
- 纯粹的发布/订阅模式
- 不存储任何值
- 新订阅者只能收到订阅后发出的值
javascript
javascript
const subject = new Subject();
subject.subscribe(v => console.log(`A: ${v}`)); // 不会立即收到值
subject.next(1); // A: 1
subject.next(2); // A: 2
subject.subscribe(v => console.log(`B: ${v}`)); // 不会收到之前的值
subject.next(3); // A: 3, B: 3
2. BehaviorSubject
基本特性:
- 存储"当前"值
- 新订阅者立即收到最后一个值
- 必须提供初始值
javascript
css
const behaviorSubject = new BehaviorSubject(0);
behaviorSubject.subscribe(v => console.log(`A: ${v}`)); // A: 0
behaviorSubject.next(1); // A: 1
behaviorSubject.next(2); // A: 2
behaviorSubject.subscribe(v => console.log(`B: ${v}`)); // B: 2
behaviorSubject.next(3); // A: 3, B: 3
3. ReplaySubject
基本特性:
- 可以缓存指定数量的值
- 新订阅者会收到缓存的所有值
- 可以设置缓存窗口时间
javascript
ini
const replaySubject = new ReplaySubject(2); // 缓存最后2个值
replaySubject.next(1);
replaySubject.next(2);
replaySubject.next(3);
replaySubject.subscribe(v => console.log(`A: ${v}`));
// 输出: A: 2, A: 3 (收到最后2个值)
4. AsyncSubject
基本特性:
- 只在 complete 时发送最后一个值
- 如果没有值则什么都不发送
- 新订阅者在 complete 后也会收到最后一个值
javascript
ini
const asyncSubject = new AsyncSubject();
asyncSubject.subscribe(v => console.log(`A: ${v}`));
asyncSubject.next(1);
asyncSubject.next(2);
asyncSubject.next(3);
asyncSubject.complete(); // A: 3
5. VoidSubject
基本特性:
- 专门用于不携带数据的事件通知
- 只关心事件发生,不关心值
javascript
javascript
const voidSubject = new Subject<void>();
voidSubject.subscribe(() => console.log('事件发生了'));
voidSubject.next();
比较表格
特性 | Subject | BehaviorSubject | ReplaySubject | AsyncSubject | VoidSubject |
---|---|---|---|---|---|
需要初始值 | 否 | 是 | 否 | 否 | 否 |
存储值 | 否 | 最后一个 | 可配置数量 | 最后一个 | 否 |
新订阅者接收的值 | 无 | 最后一个 | 缓存的所有 | 完成时的最后 | 无 |
完成前发送值 | 是 | 是 | 是 | 否 | 是 |
典型用途 | 事件总线 | 状态管理 | 历史记录 | 最终结果 | 无值事件 |
使用建议
- 需要初始状态 → BehaviorSubject
- 只需要最新事件 → Subject
- 需要历史记录 → ReplaySubject
- 只关心最终结果 → AsyncSubject
- 无值通知 → VoidSubject
选择哪种 Subject 取决于你的具体需求,特别是关于值存储和新订阅者行为的要求。