RxJS-Subject, BehaviorSubject, ReplaySubject, AsyncSubject
RxJS-Subject, BehaviorSubject, ReplaySubject, AsyncSubject
1. Subject
直接用subject
的next
方法传值,所有订阅的observer
就会接收到,因为Subject
本身是Observable
。它会在内部管理一份observer
的事件清单
const subject = new Subject();
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 1
// next: 2
// next: 3 等待1s
subject.next(1);
subject.next(2);
setTimeout(() => {
subject.next(3);
}, 1000);
// 这里只会收到`3`,因为只有next(3)是该订阅之后执行的
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 3
2. BehaviorSubject
很多时候我们会希望Subject
能代表当前的状态,而不是单纯的事件发送,也就是说如果有一个新的订阅,我们希望Subject
能立即给出最新的值,而不是订阅后要等待执行next()
才能收到新值。
const subject = new Subject();
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 1
// next: 2
subject.next(1);
subject.next(2);
setTimeout(() => {
// 这里不会收到任何消息,因为是在next()之后订阅的
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
}, 1000);
我们希望subject
订阅时就能立即收到2
,可以用BehaviorSubject
。
BehaviorSubject
跟Subject
最大的不同就是BehaviorSubject
是用来呈现当前的值,而不是单纯的发送事件。BehaviorSubject
会记住最新一次发送的元素,并把该元素当作目前的值,在使用上BehaviorSubject
需要传入一个参数来代表默认的状态,示例如下:
const subject = new BehaviorSubject(0); // 0为默认值
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 0
// next: 100
subject.next(100);
setTimeout(() => {
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 100
}, 1000);
这个示例可以看得出来BehaviorSubject
在创建时就需要给定一个状态,并在之后任何一次订阅,就会先送出最新的状态。其实这种行为就是一种状态而非单纯的事件。
3. ReplaySubject
在某些时候我们会希望Subject
代表事件,但又能在新订阅时重新发送最后的几个元素,这时我们就可以用ReplaySubject
。示例如下
const subject = new ReplaySubject(2); // 重新发送最后两个元素
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 1
// next: 2
// next: 3
subject.next(1);
subject.next(2);
subject.next(3);
setTimeout(() => {
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// next: 2
// next: 3
}, 1000);
可能会有人认为ReplaySubject(1)
是不是就等同于BehaviorSubject,其实是不一样的,BehaviorSubject
在建立时就会有起始值,比如BehaviorSubject(0)
起始值就是0
,BehaviorSubject
是代表着状态而ReplaySubject
只是事件的重放而已。
4. AsyncSubject
AsyncSubject
是最怪的一个变形,他有点像是operator last
,会在subject
结束后送出最后一个值。其实这个行为跟Promise
很像,都是等到事情结束后送出最后一个值。示例如下
const subject = new AsyncSubject();
subject.subscribe({
next: value => console.log('next: ' + value),
error: error => console.log('error: ' + error),
complete: () => console.log('complete!')
});
// 等待1s
// next: 3
// complete!
subject.next(1);
subject.next(2);
subject.next(3);
setTimeout(() => {
subject.complete();
}, 1000);