What are they, after all? When to use what!
I have been using Subjects in reactive programming. But, I have always faced difficulty in understanding when to use what type of subject. In this article I’d be going through the types of subjects.
What is an Observable?
In a nutshell, Observable is a function which returns a stream of values to an observer over time. Observer reacts to whatever values an Observable emits. It implements the Observer Design Pattern.
Observer Design Pattern: A publisher publishes data and the consumer
subscribes to the publisher to receive the data and
unsubscribes to stop receiving that data. Publisher doesn’t know who you are and how you are subscribing, it just delivers the value to you because you are a subscriber (loose coupling).
What is an Observer?
An Observer is the consumer of the values emitted by the Observable. It is an object with 3 callback methods
error(e). Observable will call Observer’s
next(value)method to emit data.
What is a Subject?
Subjects are a special kind of Observables. They can be Observables and Observers both. If we’re using Subject as Observable, then to emit values we can use
next(value). Subjects are similar to EventEmitters; they just emit the same data to all its subscribers and maintain a registry of many listeners.
Basic usage of a Subject is to get the value from the publisher and give it to all of its consumers.
Here, we created a Subject and attached two observers to it and we are feeding some values to the Subject. On emitting the first value both the subscribers receive at the same time.
Since, Subjects can also be an Observer, we can pass a subject to the subscribe method of an Observable. Here, if you could notice all of the subscribers are getting the same value, we just converted the unicast behaviour of an Observable to multicast. Later, in this article we’ll see what multicast means.
Subjects are not reusable
Subjects can’t be reused once they are completed or throw an error. If you’d try to call
next(value) on a Subject it would silently ignore the notification. If you want a specific error instead of an ignored notification you can unsubscribe to the Subject.
When to use Subjects and Observables?
Observable is generally unicast or cold, but Subject is multicast.
Subjects are basically multicast Observables. They make sure all of the subscribers get the same value. But Observables are unicast because each observer has its own instance of the data producer. Internally to the Subject, subscribe does not invoke a new execution that delivers values.
In the above example, we created a currentUserSubject which would notify us whenever our current logged in user changes. So, if we are subscribing to currentUserSubject in 10 different places in our application, this would notify and give all the subscribers the same value.
When you want to observe the incoming data only once somewhere in your application, but you want to use that data simultaneously around your application when the data arrives. Whenever the subject emits some value all of its subscribers would get the same value. For example, you’ve to perform one function in one component which would affect 10 different components, then you should create subjects and subscribe to it in 10 components. This type of behaviour is a multicast behaviour.
With Observables, every consumer would get a different data. For example, if we are fetching data using
http.get() and calling a url, every time a consumer would subscribe to that Observable, it’d make a new network request and would fetch you a different data every time. Hence, Observables work in an unicast way. But we’ve seen above how to make them multicast using Subjects.
Now, we’ve established the basics of Observable, Observer and Subject. Let’s talk about the types of Subjects and how they are useful.
Types Of Subjects
BehaviorSubject stores the last emitted value. Whenever a new subscriber comes, it will get the last emitted value, even if it comes much later than the subject emitted value. We create a BehaviorSubject by passing an initial value. The real world usage of BehaviorSubject is to share data between components.
BehaviorSubjects are useful for representing “values over time”. For instance, an event stream of birthdays is a Subject, but the stream of a person’s age would be a BehaviorSubject
In the above example, we created a Subject and two subscribers, they are getting the initial value emitted by the Subject.
Then, later we created a new subscriber much after the subject has emitted some values. And this new subscriber received the last emitted value, which is ‘b’.
ReplaySubject works the same as BehaviorSubject. But it has the capability of storing the last emitted n values. It stores the values from the Subject and replays whenever a subscriber arrives.
In the above example, we are creating a Subject by passing the number of old values we want our subscribers to get every time they subscribe or get notified. You can think of this something like, the magazine publisher would give you the latest 3 published magazines every time you subscribe for a type of magazine.
AsyncSubject emits its last value only on
COMPLETION. The last value of the Observable execution is sent to its observers, only when the execution completes. This is the only Subject that would emit a value even after it completes.
Here, both the subscribers are getting only one (last emitted) value when the Subject calls the
- Subjects emit data.
- Subjects can be used as an Observable and an Observer.
- Subjects can’t be reused.
- Subjects work in a multicast manner.
Hope you got the basic understanding of the Subjects in RxJS. Next time you’d be able to use them in your code with proper understanding (unlike me 😉).