Subject的分类

Subject包含四种类型,BehaviorSubject,AsyncSubject,ReplaySubject,Subject

BehaviorSubject

  1. Observer会接收到BehaviorSubject被订阅之前的最后一个数据,再接收订阅之后发射过来的数据。如果BehaviorSubject被订阅之前没有发送任何数据,则会发送一个默认数据。
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
3000
4000

在这里0是默认值,如果修改下代码,再订阅之前再发射一个事件

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);

执行结果

2
3000
4000

这次丢弃了默认值,而发射1。因为BehaviorSubject 每次只会发射调用subscribe()方法之前的最后一个事件和调用subscribe()方法之后的事件。

  1. 每当新增一个观察者的时候,Subject 能够立即发出当前最新的值,而不是没有任何响应,也就是说如果再次订阅,会获得最新的值。
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)
});

执行结果

0
3000
3000

AsyncSubject

  1. Observer会接收AsyncSubject的onComplete()之前的最后一个数据。
let mySubject = new AsyncSubject();

mySubject.subscribe(r => {
console.log(r)
})

mySubject.next(1);

mySubject.next(2);

mySubject.complete();

执行结果

2

修改下代码

let mySubject = new AsyncSubject();

mySubject.subscribe(r => {
console.log(r)
})

mySubject.next(1);

mySubject.complete();

mySubject.next(2);

执行结果

1

注意,subject.onComplete()必须要调用才会开始发送数据,否则Subscriber将不接收任何数据

ReplaySubject

  1. ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。
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
//一秒后
1
2

再看一个例子

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
//一秒后
1
2
//两秒后
2000
2000

2.同样的,ReplaySubject还接受一个初始参数来规定回放多少个值

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);

执行结果

1
2
3
//一秒后
2
3

Subject

Subject 只接收被订阅之后发送的数据。

let mySubject = new Subject();

mySubject.subscribe(r => {
console.log(r)
})

mySubject.next(1);

mySubject.next(2);

执行结果

1
2

如果修改代码

let mySubject = new Subject();

mySubject.next(1);

mySubject.subscribe(r => {
console.log(r)
})

mySubject.next(2);

结果

2

最后,一句话总结一下四个Subject的特性。

Subject 特征
AsyncSubject 不论订阅发生在什么时候,只会发射最后一个数据
BehaviorSubject 发送订阅之前一个数据和订阅之后的全部数据
ReplaySubject 不论订阅发生在什么时候,都发射全部数据
Subject 发送订阅之后全部数据