I'm looking into Angular RxJs patterns and I don't understand the difference between a BehaviorSubject
and an Observable
.
From my understanding, a BehaviorSubject
is a value that can change over time (can be subscribed to and subscribers can receive updated results). This seems to be the exact same purpose of an Observable
.
When would you use an Observable
vs a BehaviorSubject
? Are there benefits to using a BehaviorSubject
over an Observable
or vice versa?
Observable is a Generic, and BehaviorSubject is technically a sub-type of Observable because BehaviorSubject is an observable with specific qualities. An observable can be created from both Subject and BehaviorSubject using subject.
The one and major difference between observable and the subject is that observables are unicast (each subscribed Observer owns an independent execution of the Observable) while the subject is multicast which means it is like an event emitter, it maintains the registry of listener(s) and updates each listener every time ...
As we know multiple components share the common data and always need updated shared data. In such scenarios most of the time BehaviorSubject is used which acts as a single store to hold updated shared data. BehaviorSubject is both observer and type of observable.
Often Observable is preferred over Promise because it provides the features of Promise and more. With Observable it doesn't matter if you want to handle 0, 1, or multiple events. You can utilize the same API in each case. Observable also has the advantage over Promise to be cancellable.
BehaviorSubject is a type of subject, a subject is a special type of observable so you can subscribe to messages like any other observable. The unique features of BehaviorSubject are:
next()
onnext
getValue()
method.Unique features of a subject compared to an observable are:
In addition, you can get an observable from behavior subject using the asObservable()
method on BehaviorSubject
.
Observable is a Generic, and BehaviorSubject
is technically a sub-type of Observable because BehaviorSubject is an observable with specific qualities.
Example with 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
Example 2 with regular subject:
// 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
An observable can be created from both Subject
and BehaviorSubject
using subject.asObservable()
.
The only difference being you can't send values to an observable using next()
method.
In Angular services, I would use BehaviorSubject
for a data service as an angular service often initializes before component and behavior subject ensures that the component consuming the service receives the last updated data even if there are no new updates since the component's subscription to this data.
One very very important difference. Since Observable is just a function, it does not have any state, so for every new Observer, it executes the observable create code again and again. This results in:
The code is run for each observer . If its a HTTP call, it gets called for each observer
This causes major bugs and inefficiencies
BehaviorSubject (or Subject ) stores observer details, runs the code only once and gives the result to all observers .
Ex:
JSBin: http://jsbin.com/qowulet/edit?js,console
// --- 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>
Output :
"observer 1: 0.7184075243594013" "observer 2: 0.41271850211336103" "observer subject 1: 0.8034263165479893" "observer subject 2: 0.8034263165479893"
Observe how using Observable.create
created different output for each observer, but BehaviorSubject
gave the same output for all observers. This is important.
Other differences summarized.
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ 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 ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With