Subject vs BehaviorSubject vs ReplaySubject in Angular
I've been looking to understand those 3:
- Subject
- BehaviorSubject
- ReplaySubject
I would like to use them and know when and why, what are the benefits of using them and although I've read the documentation, watched tutorials and searched google I've failed to make any sense of this.
So what are their purpose? A real-world case would be most appreciated it does not have to even code.
I would prefer a clean explanation not just "a+b => c you are subscribed to ...."
Thank you
Solution 1:
It really comes down to behavior and semantics. With a
Subject
- a subscriber will only get published values that were emitted after the subscription. Ask yourself, is that what you want? Does the subscriber need to know anything about previous values? If not, then you can use this, otherwise choose one of the others. For example, with component-to-component communication. Say you have a component that publishes events for other components on a button click. You can use a service with a subject to communicate.-
BehaviorSubject
- the last value is cached. A subscriber will get the latest value upon initial subscription. The semantics for this subject is to represent a value that changes over time. For example a logged in user. The initial user might be an anonymous user. But once a user logs in, then the new value is the authenticated user state.The
BehaviorSubject
is initialized with an initial value. This is sometimes important to coding preference. Say for instance you initialize it with anull
. Then in your subscription, you need to do a null check. Maybe OK, or maybe annoying. -
ReplaySubject
- it can cache up to a specified number of emissions. Any subscribers will get all the cached values upon subscription. When would you need this behavior? Honestly, I have not had any need for such behavior, except for the following case:If you initialize a
ReplaySubject
with a buffer size of1
, then it actually behaves just like aBehaviorSubject
. The last value is always cached, so it acts like a value changing over time. With this, there is no need for anull
check like in the case of theBehaviorSubject
initialized with anull
. In this instance, no value is ever emitted to the subscriber until the first publishing.
So it really comes down to the behavior you are expecting (as for which one to use). Most of the time you will probably want to use a BehaviorSubject
because what you really want to represent is that "value over time" semantic. But I personally don't see anything wrong with the substitution of ReplaySubject
initialized with 1
.
What you want to avoid is using the vanilla Subject
when what you really need is some caching behavior. Take for example you are writing a routing guard or a resolve. You fetch some data in that guard and set it in a service Subject
. Then in the routed component you subscribe to the service subject to try to get that value that was emitted in the guard. OOPs. Where's the value? It was already emitted, DUH. Use a "caching" subject!
See also:
- What are RxJS Subject's and the benefits of using them?
Solution 2:
A handy summary of the different observable types, non intuitive naming i know lol.
-
Subject
- A subscriber will only get published values thereon-after the subscription is made. -
BehaviorSubject
- New subscribers get the last published value OR initial value immediately upon subscription. -
ReplaySubject
- New subscribers get all previously published value(s) immediately upon subscription