「这是我参与2022首次更文挑战的第33天,活动详情查看:2022首次更文挑战」
在前面的章节中,我们已经接触过 Subject,这一节就来系统的学习一下 Subject 是什么以及在实际开发中 Subject 的应用。
在 Rxjs 中有 Subject、BehaviorSubject、ReplaySubject 和 AsyncSubject 几种不同的 Subject 类型,它们分别对应着不同的作用。
Subject
Subject 是最普通的 Subject,它既有 Observable 的能力,又有 Observer 的能力,订阅一个 Subject 和订阅一个 Observable 看起来是一样的,在 Subject 上有 next 方法,使用 next 可以发送数据,这个数据可以多播给所有的观察者。
举个例子:
const subject = new Subject<number>();
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
subject.next(1);
subject.next(2);
// Logs:
// observerA: 1
// observerB: 1
// observerA: 2
// observerB: 2
上面的是非常常见的用法,使用 next 向订阅者发送数据,此外 subject 也可以作为订阅者订阅其他 Observable 的数据:
const subject = new Subject<number>();
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
const observable = from([1, 2, 3]);
observable.subscribe(subject); // You can subscribe providing a Subject
// Logs:
// observerA: 1
// observerB: 1
// observerA: 2
// observerB: 2
// observerA: 3
// observerB: 3
BehaviorSubject
BehaviorSubject 与普通 Subject 的区别在于它可以拥有一个初始值,这样可以保证无论何时它都可以有一个当前值,无论何时订阅都可以拿到这个最新值,还可以随时通过 value 属性获取最新的值数据,BehaviorSubject 是实际开发中最常用的 Subject 类型,可以看一下用法:
const subject = new BehaviorSubject(0); // 0 is the initial value
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.next(1);
subject.next(2);
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
subject.next(3);
// Logs
// observerA: 0
// observerA: 1
// observerA: 2
// observerB: 2
// observerA: 3
// observerB: 3
我们可以利用 BehaviorSubject 处理很多有初始值的场景,比如用来实现 redux 的初始值能力等。
ReplaySubject
ReplaySubject 可以算得上是 BehaviorSubject 的增强版,它的能力也是重播旧数据,区别在于 BehaviorSubject 只能保留一个旧值,而 ReplaySubject 可以保留多个,它可以保留一定数量或一定时间内产生的值,每次新的订阅到的时候可以还原这个曾经发出值的过程。举个例子:
const subject = new ReplaySubject(3); // buffer 3 values for new subscribers
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
subject.next(5);
// Logs:
// observerA: 1
// observerA: 2
// observerA: 3
// observerA: 4
// observerB: 2
// observerB: 3
// observerB: 4
// observerA: 5
// observerB: 5
AsyncSubject
AsyncSubject 是另一种特殊的 Subject,它的行为是只发送最后一个值,只会在完成时发送,类似于 last 的效果,可以看一下例子:
const subject = new AsyncSubject();
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
subject.next(5);
subject.complete();
// Logs:
// observerA: 5
// observerB: 5
上面介绍的是几种不同类型的 Subject,在实际应用中,Subject 也可以不发送值,有时候我们只需要触发一个行为,不需要传递信息,这时可以 next 传递一个空来表示发一个信号的效果,这种经常在把 Subject 作为事件发生器使用时用到。