BehaviorSubject
一般的 Subject 可能会存在这样一个问题,某个 Observer 订阅的时间太晚了,导致他错过了最近的 Observable 发出的值:
const subject = new Rx.Subject();
const observerA = {
next: x => console.log(`A next ${x}`),
error: e => console.error(`A error ${e}`),
complete: () => console.log('A done')
};
subject.subscribe(observerA);
console.log('observerA subscribed');
const observerB = {
next: x => console.log(`B next ${x}`),
error: e => console.error(`B error ${e}`),
complete: () => console.log('B done')
};
subject.next(1);
subject.next(2);
subject.next(3);
setTimeout(() => {
subject.subscribe(observerB);
console.log('observerB subscribed');
}, 2000);
/* 程序输出:
"observerA subscribed"
"A next 1"
"A next 2"
"A next 3"
"observerB subscribed"
*/
在这个例子中,observerB
就因为订阅地太晚了,错过了 subject
最新发出的值 3
:
subject: 1--2--3
observerA: 1--2--3
observerB: B
如果我们想各个观察者总能看到最近一次的值,那么就可以使用 BehaviorSubject:
const subject = new Rx.BehaviorSubject(0);
const observerA = {
next: x => console.log(`A next ${x}`),
error: e => console.error(`A error ${e}`),
complete: () => console.log('A done')
};
subject.subscribe(observerA);
console.log('observerA subscribed');
const observerB = {
next: x => console.log(`B next ${x}`),
error: e => console.error(`B error ${e}`),
complete: () => console.log('B done')
};
subject.next(1);
subject.next(2);
subject.next(3);
setTimeout(() => {
subject.subscribe(observerB);
console.log('observerB subscribed');
}, 2000);
/* 程序输出:
"A next 0"
"observerA subscribed"
"A next 1"
"A next 2"
"A next 3"
"B next 3"
"observerB subscribed"
*/
确切的说,BehaviorSubject 并不只是留住了最后一次值,而是只有一个值,它反映了 “ 随时间变化的值 ” 。因此,在使用 BehaviorSubject 时,需要确定初始值。一个现实中的能反映 Subject 和 BehaviorSubject 区别的例子,就是 年龄 和 生日。人只有一个年龄,并且始终拥有年龄,它随着时间变化,是一个单值的变化,所以是一个 BehaaviorSubject,而生日则每隔一年都会到来,是一个事件流,所以是一个 Subject。