Subject的分类
Subject包含四种类型,BehaviorSubject,AsyncSubject,ReplaySubject,Subject
BehaviorSubject
- Observer会接收到BehaviorSubject被订阅之前的最后一个数据,再接收订阅之后发射过来的数据。如果BehaviorSubject被订阅之前没有发送任何数据,则会发送一个默认数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function set_timeout(Observable: any, time: number) { setTimeout(() => { Observable.next(time) }, time); }
let mySubject = new BehaviorSubject(0);
mySubject.subscribe(r => { console.log(r) });
set_timeout(mySubject, 3000);
set_timeout(mySubject, 4000);
|
执行结果
在这里0是默认值,如果修改下代码,再订阅之前再发射一个事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function set_timeout(Observable: any, time: number) { setTimeout(() => { Observable.next(time) }, time); }
let mySubject = new BehaviorSubject(0);
mySubject.next(1);//订阅之前发射一次事件
mySubject.next(2);//订阅之前发射一次事件
mySubject.subscribe(r => { console.log(r) });
set_timeout(mySubject, 3000);
set_timeout(mySubject, 4000);
|
执行结果
这次丢弃了默认值,而发射1。因为BehaviorSubject 每次只会发射调用subscribe()方法之前的最后一个事件和调用subscribe()方法之后的事件。
- 每当新增一个观察者的时候,Subject 能够立即发出当前最新的值,而不是没有任何响应,也就是说如果再次订阅,会获得最新的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function set_timeout(Observable: any, time: number) { setTimeout(() => { Observable.next(time) }, time); }
let mySubject = new BehaviorSubject(0);
mySubject.subscribe(r => { console.log(r) });
set_timeout(mySubject, 3000);
mySubject.subscribe(r => { console.log(r) });
|
执行结果
AsyncSubject
- Observer会接收AsyncSubject的onComplete()之前的最后一个数据。
1 2 3 4 5 6 7 8 9 10 11
| let mySubject = new AsyncSubject();
mySubject.subscribe(r => { console.log(r) })
mySubject.next(1);
mySubject.next(2);
mySubject.complete();
|
执行结果
修改下代码
1 2 3 4 5 6 7 8 9 10 11
| let mySubject = new AsyncSubject();
mySubject.subscribe(r => { console.log(r) })
mySubject.next(1);
mySubject.complete();
mySubject.next(2);
|
执行结果
注意,subject.onComplete()必须要调用才会开始发送数据,否则Subscriber将不接收任何数据
ReplaySubject
- ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let mySubject = new ReplaySubject();
mySubject.subscribe(r => { console.log(r) })
mySubject.next(1);
mySubject.next(2);
setTimeout(() => { mySubject.subscribe(r => { console.log(r) }) }, 1000);
|
执行结果
再看一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function set_timeout(Observable: any, time: number) { setTimeout(() => { Observable.next(time) }, time); }
let mySubject = new ReplaySubject();
mySubject.subscribe(r => { console.log(r) })
mySubject.next(1);
mySubject.next(2);
setTimeout(() => { mySubject.subscribe(r => { console.log(r) }) }, 1000);
set_timeout(mySubject, 2000);
|
执行结果
1 2 3 4 5 6 7 8
| 1 2 //一秒后 1 2 //两秒后 2000 2000
|
2.同样的,ReplaySubject还接受一个初始参数来规定回放多少个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let mySubject = new ReplaySubject(2);
mySubject.subscribe(r => { console.log(r) })
mySubject.next(1);
mySubject.next(2);
mySubject.next(3);
setTimeout(() => { mySubject.subscribe(r => { console.log(r) }) }, 1000);
|
执行结果
Subject
Subject 只接收被订阅之后发送的数据。
1 2 3 4 5 6 7 8 9
| let mySubject = new Subject();
mySubject.subscribe(r => { console.log(r) })
mySubject.next(1);
mySubject.next(2);
|
执行结果
如果修改代码
1 2 3 4 5 6 7 8 9
| let mySubject = new Subject();
mySubject.next(1);
mySubject.subscribe(r => { console.log(r) })
mySubject.next(2);
|
结果
最后,一句话总结一下四个Subject的特性。
| Subject|特征|
|-| :- | :-: | -: |
|AsyncSubject|不论订阅发生在什么时候,只会发射最后一个数据|
|BehaviorSubject|发送订阅之前一个数据和订阅之后的全部数据|
|ReplaySubject|不论订阅发生在什么时候,都发射全部数据|
|Subject|发送订阅之后全部数据|