我正在研究 Angular RxJs 模式,但我不了解BehaviorSubject
和Observable
之间的区别。
据我了解, BehaviorSubject
是一个随时间变化的值(可以订阅,订阅者可以接收更新的结果)。这似乎与Observable
目的完全相同。
什么时候使用Observable
和BehaviorSubject
?在Observable
上使用BehaviorSubject
有好处,反之亦然吗?
BehaviorSubject是主题的一种,主题是可观察的特殊类型,因此您可以像其他任何可观察对象一样订阅消息。 BehaviorSubject 的独特功能是:
next()
,它也必须始终在订阅时返回一个值。onnext
getValue()
方法以不可观察的代码检索主题的最后一个值。与可观察对象相比,对象的独特特征是:
BehaviorSubject
上asObservable()
方法从行为主体获取可观察对象。
Observable是泛型,而BehaviorSubject
从技术上讲是 Observable 的子类型,因为 BehaviorSubject 是具有特定质量的 Observable。
具有BehaviorSubject 的示例:
// Behavior Subject
// a is an initial value. if there is a subscription
// after this, it would get "a" value immediately
let bSubject = new BehaviorSubject("a");
bSubject.next("b");
bSubject.subscribe(value => {
console.log("Subscription got", value); // Subscription got b,
// ^ This would not happen
// for a generic observable
// or generic subject by default
});
bSubject.next("c"); // Subscription got c
bSubject.next("d"); // Subscription got d
示例 2:具有常规主题:
// Regular Subject
let subject = new Subject();
subject.next("b");
subject.subscribe(value => {
console.log("Subscription got", value); // Subscription wont get
// anything at this point
});
subject.next("c"); // Subscription got c
subject.next("d"); // Subscription got d
可以使用subject.asObservable()
Subject
和BehaviorSubject
创建可观察对象。
唯一的区别是您无法使用next()
方法将值发送给可观察对象。
在 Angular 服务中,我将对BehaviorSubject
,因为有角度的服务通常在组件和行为主体确保使用该服务的组件接收到最后更新的数据之前就进行初始化,即使自组件订阅该数据以来没有新的更新也是如此。
一个非常非常重要的区别。由于 Observable 只是一个函数,它没有任何状态,因此对于每个新的 Observer,它都会一次又一次地执行可观察的创建代码。结果是:
该代码针对每个观察者运行。如果是 HTTP 调用,则会为每个观察者调用
这会导致重大错误和效率低下
BehaviorSubject(或 Subject)存储观察者详细信息,仅运行一次代码并将结果提供给所有观察者。
前任:
JSBin:http ://jsbin.com/qowulet/edit?js,控制台
// --- Observable ---
let randomNumGenerator1 = Rx.Observable.create(observer => {
observer.next(Math.random());
});
let observer1 = randomNumGenerator1
.subscribe(num => console.log('observer 1: '+ num));
let observer2 = randomNumGenerator1
.subscribe(num => console.log('observer 2: '+ num));
// ------ BehaviorSubject/ Subject
let randomNumGenerator2 = new Rx.BehaviorSubject(0);
randomNumGenerator2.next(Math.random());
let observer1Subject = randomNumGenerator2
.subscribe(num=> console.log('observer subject 1: '+ num));
let observer2Subject = randomNumGenerator2
.subscribe(num=> console.log('observer subject 2: '+ num));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.3/Rx.min.js"></script>
输出 :
"observer 1: 0.7184075243594013"
"observer 2: 0.41271850211336103"
"observer subject 1: 0.8034263165479893"
"observer subject 2: 0.8034263165479893"
观察使用Observable.create
如何为每个观察者创建不同的输出,但是BehaviorSubject
为所有观察者提供了相同的输出。这个很重要。
总结了其他差异。
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Observable ┃ BehaviorSubject/Subject ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Is just a function, no state ┃ Has state. Stores data in memory ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Code run for each observer ┃ Same code run ┃
┃ ┃ only once for all observers ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Creates only Observable ┃Can create and also listen Observable┃
┃ ( data producer alone ) ┃ ( data producer and consumer ) ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Usage: Simple Observable with only ┃ Usage: ┃
┃ one Obeserver. ┃ * Store data and modify frequently ┃
┃ ┃ * Multiple observers listen to data ┃
┃ ┃ * Proxy between Observable and ┃
┃ ┃ Observer ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
可观察者和对象都是可观察者的手段,观察者可以追踪它们。但是它们都有一些独特的特征。此外,共有 3 种类型的主题,每个主题又具有独特的特征。让我们尝试了解它们中的每一个。
您可以在 stackblitz上找到实际示例。 (您需要检查控制台以查看实际输出)
Observables
他们很冷:当他们至少有一个观察者时,代码就会被执行。
创建数据副本: Observable 为每个观察者创建数据副本。
单向:观察者无法将值分配给可观察(原始 / 主)。
Subject
它们很热:即使没有观察者,代码也会被执行,价值也会得到传播。
共享数据:在所有观察者之间共享相同的数据。
双向:观察者可以将值分配给可观察(原始 / 主)。
如果正在使用主题,则您会错过创建观察者之前广播的所有值。所以这是重播主题
ReplaySubject
它们很热:即使没有观察者,代码也会被执行,价值也会得到传播。
共享数据:在所有观察者之间共享相同的数据。
双向:观察者可以将值分配给可观察(原始 / 主)。加
重播消息流:无论何时订阅重播主题,您都将收到所有广播的消息。
在主题和重播主题中,您无法将初始值设置为可观察。行为主体来了
BehaviorSubject
它们很热:即使没有观察者,代码也会被执行,价值也会得到传播。
共享数据:在所有观察者之间共享相同的数据。
双向:观察者可以将值分配给可观察(原始 / 主)。加
重播消息流:无论何时订阅重播主题,您都将收到所有广播的消息。
您可以设置初始值:您可以使用默认值初始化可观察对象。