我一直想了解这3个:
主题 BehaviorSubject ReplaySubject
我想使用它们,知道什么时候和为什么,使用它们的好处是什么,虽然我已经阅读了文档,观看教程和搜索谷歌,但我没有搞清楚这一点。
那么它们的目的是什么呢?如果是真实的情况,甚至不需要编写代码,那就最好不过了。
我更喜欢一个干净的解释,而不仅仅是“a+b => c您订阅了....”
谢谢你!
我一直想了解这3个:
主题 BehaviorSubject ReplaySubject
我想使用它们,知道什么时候和为什么,使用它们的好处是什么,虽然我已经阅读了文档,观看教程和搜索谷歌,但我没有搞清楚这一点。
那么它们的目的是什么呢?如果是真实的情况,甚至不需要编写代码,那就最好不过了。
我更喜欢一个干净的解释,而不仅仅是“a+b => c您订阅了....”
谢谢你!
当前回答
正如在一些帖子中提到的,公认的答案是错误的,因为BehaviorSubject != ReplaySubject(1),这不仅仅是编码风格的偏好。
评论中经常提到“守卫”,这也是我发现重放主题用例最多的地方。更具体地说,如果你有一个类似于取(1)的情况你不只是想取初值。
请看下面的例子:
ngOnInit() {
const behaviorSubject = new BehaviorSubject<boolean>(null);
const replaySubject = new ReplaySubject<boolean>(1);
this.checkLoggedIn(behaviorSubject, 'behaviorSubject');
this.checkLoggedIn(replaySubject, 'replaySubject');
behaviorSubject.next(true);
replaySubject.next(true);
}
checkLoggedIn($userLoggedIn: Observable<boolean>, id: string) {
$userLoggedIn.pipe(take(1)).subscribe(isLoggedIn => {
if (isLoggedIn) {
this.result[id] = 'routed to dashboard';
} else {
this.result[id] = 'routed to landing page';
}
});
}
结果是:
{
"behaviorSubject": "routed to landing page",
"replaySubject": "routed to dashboard"
}
在这种情况下,你显然需要一个ReplaySubject!工作代码:https://stackblitz.com/edit/replaysubject-vs-behaviorsubject?file=src%2Fapp%2Fapp.component.ts
其他回答
Subject:在订阅时,它总是获得在订阅后推送的数据,即之前推送的值没有收到。
const mySubject = new Rx.Subject(); mySubject.next (1); const subscription1 = mySubject订阅(x => { console.log('从订阅1:',x); }); mySubject.next (2); const subscription2 = mySubject。订阅(x => { console.log('从订阅2:',x); }); mySubject.next (3); subscription1.unsubscribe (); mySubject.next (4); < script src = " https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.12/Rx.min.js " > < /脚本>
在这个例子中,结果会打印在控制台中:
From subscription 1: 2
From subscription 1: 3
From subscription 2: 3
From subscription 2: 4
请注意,延迟到达的订阅如何错过了推入主题的一些数据。
重放主题:可以通过保留将被发送到新订阅的先前值的缓冲区来帮助。
这里有一个重放主题的使用示例,其中保留了2个先前值的缓冲区,并在新的订阅上发出:
const mySubject = new Rx.ReplaySubject(2); mySubject.next (1); mySubject.next (2); mySubject.next (3); mySubject.next (4); mySubject。订阅(x => { console.log('From 1st sub:', x); }); mySubject.next (5); mySubject。订阅(x => { console.log('From 2nd sub:', x); }); < script src = " https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.12/Rx.min.js " > < /脚本>
这是我们在控制台得到的结果:
From 1st sub: 3
From 1st sub: 4
From 1st sub: 5
From 2nd sub: 4
From 2nd sub: 5
行为主题:类似于重放主题,但只会重新发出最后发出的值,或者如果之前没有发出值,则会重新发出默认值:
const mySubject = new Rx。BehaviorSubject(“嘿!”); mySubject。订阅(x => { console.log('From 1st sub:', x); }); mySubject.next (5); mySubject。订阅(x => { console.log('From 2nd sub:', x); }); < script src = " https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.12/Rx.min.js " > < /脚本>
结果是:
From 1st sub: Hey now!
From 1st sub: 5
From 2nd sub: 5
参考:https://alligator.io/rxjs/subjects/
正如在一些帖子中提到的,公认的答案是错误的,因为BehaviorSubject != ReplaySubject(1),这不仅仅是编码风格的偏好。
评论中经常提到“守卫”,这也是我发现重放主题用例最多的地方。更具体地说,如果你有一个类似于取(1)的情况你不只是想取初值。
请看下面的例子:
ngOnInit() {
const behaviorSubject = new BehaviorSubject<boolean>(null);
const replaySubject = new ReplaySubject<boolean>(1);
this.checkLoggedIn(behaviorSubject, 'behaviorSubject');
this.checkLoggedIn(replaySubject, 'replaySubject');
behaviorSubject.next(true);
replaySubject.next(true);
}
checkLoggedIn($userLoggedIn: Observable<boolean>, id: string) {
$userLoggedIn.pipe(take(1)).subscribe(isLoggedIn => {
if (isLoggedIn) {
this.result[id] = 'routed to dashboard';
} else {
this.result[id] = 'routed to landing page';
}
});
}
结果是:
{
"behaviorSubject": "routed to landing page",
"replaySubject": "routed to dashboard"
}
在这种情况下,你显然需要一个ReplaySubject!工作代码:https://stackblitz.com/edit/replaysubject-vs-behaviorsubject?file=src%2Fapp%2Fapp.component.ts
被点赞最多的回答显然是错误的:
如果你初始化一个ReplaySubject缓冲区大小为1,那么它的行为实际上就像一个BehaviorSubject
这并不完全正确;看看这篇关于两者区别的博客文章。例如,如果你订阅了一个完整的BehaviorSubject,你将不会收到最后一个值,但对于ReplaySubject(1),你将收到最后一个值。
这是一个不容忽视的重要区别:
const behavior = new behaviour subject (null); const replay = new ReplaySubject(1); behavior.skip(1)。订阅(v => console.log('BehaviorSubject:', v)); 重播。订阅(v => console.log('ReplaySubject:', v)); behavior.next (1); behavior.next (2); behavior.complete (); 的行为。订阅(v => console.log('晚期B订阅者:',v)); replay.next (1); replay.next (2); replay.complete (); 重播。订阅(v => console.log('后期R订阅者:',v));
查看这里的代码示例,它来自另一篇关于该主题的很棒的博客文章。
另一个不同之处在于,您可以使用BehaviorSubject的值getter来获取当前值。当您在某些情况下只需要当前值时,这是非常有用的。例如,当用户单击某个内容,而您只需要该值一次时。在这种情况下,你不需要订阅然后突然取消订阅。唯一需要的是:
BehaviorSubject bSubject = new BehaviorSubject<IBasket>(basket);
getCurrentBasketValue() {
return this.bSubject.value;
}
// ***********Subject concept ***********
let subject = new Subject<string>();
subject.next("Eureka");
subject.subscribe((data) => {
console.log("Subscriber 1 got data >>>>> "+ data);
});
subject.subscribe((data) => {
console.log("Subscriber 2 got data >>>>> "+ data);
});
// ********behaviour subject*********
// Behavior subjects need a first value
let subject1 = new BehaviorSubject<string>("First value");
subject1.asObservable().subscribe((data) => {
console.log("First subscriber got data behaviour subject>>>>> "+ data);
});
subject1.next("Second value")
Subject——订阅者只会在订阅之后获得已发布的值。 BehaviorSubject——新订阅者在订阅后立即获得最后发布的值或初始值。