RxJs Subject vs Behaviorsubject
RxJS is a powerful library that allows you to manage data streams and makes reactive programming easy for developers. RxJS is commonly used in combination with Angular because both are based on observable patterns. Two of the most frequently used RxJS classes for managing data streams are Subject and BehaviorSubject. Do you struggle with the difference between Subject vs. BehaviorSubject and you're not always sure which one to use?! I got you covered!
While both classes allow you to emit and subscribe to data events, their behavior and use cases differ. In this blog post, we'll take a deep dive into the differences between RxJS Subject and BehaviorSubject, and explore real-world examples of when you would use one over the other.
By the end of this article, you'll have a solid understanding of how to choose the right class for your data stream needs, and be able to implement them effectively in your applications. Because RxJS is mostly used in combination with Angular the examples in this blog post will be made with Angular.
Table of content:
What is RxJS Subject?
RxJs Subject is a class in the RxJS library that allows you to create an observable stream and push data events to subscribers using the next()
method. You can subscribe to this stream using the subscribe()
method, and you'll only receive events that have been emitted after the subscription started.
Now you might be thinking; Okay, but what does that mean?
Let's for example say there is a magazine company that releases a new magazine issue on a weekly basis. This new issue of the magazine is released on a specific day to all the subscribers who subscribe to the magazine. After the magazine is released there is no way of getting it if you did not receive it during the issuing moment. So you have to be subscribed to receive the magazine and you cannot get previously released issues of the magazine from the magazine company. In this example, the magazine company is the RxJS Subject, the weekly issues are the data being pushed by it and the subscribers are the subscriptions created with the subscribe() method.
RxJS Subject is a useful tool for implementing event-driven architecture and communication among multiple components, where components can communicate with each other by sending and receiving events through a central Subject.
RxJS Subject examples
Now let's have a look at how you can use this in your code. We will create an RxJS subject inside an Angular service and will subscribe to it in two different components to demonstrate and explain some things.
In the example above we create a simple Subject that sends a string to all its subscribers (in this case only 1) each time the next() method is called. We first call the next method 2 times to send a string, but there are no subscribers yet, so no one is receiving these 2 values. After that, we subscribe to the RxJS Subject. All values emitted by the Subject after we subscribed to it, are received inside the subscription callback and can be used as you see fit (in this case we just log the value).
This is not a scenario you would use in the real world, but it clearly demonstrates you do not receive any values emitted before you subscribe to the Subject. Only values emitted with the next() method after your subscription are received and logged in the callback method of the subscription.
In a real-world scenario, the subject would probably be located in a service class and one or multiple components subscribe to it and receive the emitted values. So let's change the example to a more realistic setup. To do this we will create a test service that holds the subject. When creating a Subject it's good practice to make the Subject itself immutable, meaning you cannot emit new values from everywhere only from within the class where the Subject is located. Because of this, we will also add a method to the service for updating the Subject value.
As you can see in the example we now declare the RxJS subject as a private read-only property and create a public property that holds the Subject as an Observable, making the Subject itself immutable from outside classes. There is also a simple method added to update the Subject. Now let's add subscribers to the Subject and demonstrate how you can receive the emitted values in multiple places in your application. We will just emit some random values, in a real-world scenario you would probably emit new values based on an event or user action.
The first value we emit in the app component is only received by the child components because they are subscribed at the moment the value is emitted and the app component itself is not subscribed yet. After we emit that value we add a subscription in the app component as well, all values emitted after that point are received by the app component and both child components.
When to use RxJS Subject
Event-driven architecture: You can use a Subject to implement an event-driven architecture, where multiple components can communicate with each other by sending and receiving events through a central Subject. For example, you might have a "data updated" event that is emitted whenever new data is available, and multiple components that need to react to this event can subscribe to the Subject and receive the data (or just a ping) as it is emitted.
Publisher/Subscriber pattern: You can use a Subject to implement the pub/sub pattern, where one component publishes something and other components listen and use this published value. For example, you might have a "chat message" topic that is used by multiple chat components to send and receive messages.
User interaction: You can use a Subject to handle user interaction events, such as button clicks or form submissions. For example, you might have a "submit" button that emits a "form submitted" event to the Subject. Multiple components can subscribe to this event to perform various actions when the form is submitted.
What is RxJS BehaviorSubject?
RxJs Behaviorsubject is a class in the RxJS library that allows you to create an observable stream and push data events to subscribers using the next()
method. The BehaviorSubject needs to be initialized with an initial value and holds the current (last emitted) value. You can subscribe to the data stream of the BehaviorSubject using the subscribe()
method. Subscribers receive the last emitted value the moment they subscribe to the BehaviorSubject and each new value that is emitted after the subscription.
Let's use the magazine company again to explain it with some context.
Again we have a magazine company that releases a magazine each week, just as with the Subject example. You have to be subscribed to the magazine to receive it. Let's say the magazine is issued every Monday. With the Subject, you did not receive this week's magazine if you subscribed after the magazine was released, so if you subscribe on Tuesday you do not get this week's magazine. With the BehaviorSubject you do receive this week's magazine even if you subscribe after it's released. You will get the last released magazine instantly when you subscribe to it.
RxJS BehaviorSubject examples
Hopefully, you have a good understanding of how the BehaviorSubject subject works, now let's have a look a the code. We will convert the Subject we used in the previous example to a BehaviorSubject. To do this you can simply change the Subject class to a BehaviorSubject and give it an initial value like this:
Let's take the code snippet we used before for the app and child components:
In this scenario with the BehaviorSubject, we will log different values as we did with the Subject. The subscriptions of the child components are initialized before the app component sends the new value to the BehaviorSubject so first, we log the initial value in both child components. Next in the ngAfterViewInit of the app component, we send a new value: "New value for subject", this will be logged by both child components because they already are subscribed to the BehaviorSubject, after that we subscribe to the BehaviorSubject in the app component and it will also log the last emitted value "New value for subject". All values emitted after this moment are logged by the app component and both child components.
As you might have already picked up the BehaviorSubject is suited for scenarios where you need to hold a state. The regular Subject does not hold a state and is better to use for events and signals that need to be consumed in multiple places of your application. Let's compare Subject vs Behavior subject a bit more by exploring some examples where you would use the BehaviorSubject.
When to use RxJS BehaviorSubject
User authentication status: You can use a BehaviorSubject to keep track of the current user authentication status. When the user logs in or out, you can update the BehaviorSubject's value to reflect the new authentication status. Any components that need to know the current authentication status can subscribe to the BehaviorSubject and immediately receive the current value, in addition to any subsequent changes.
Game state: You can use a BehaviorSubject to keep track of the current state of a game. For example, you might have a game that can be in one of several states, such as "waiting for players", "playing", or "game over". You can use a BehaviorSubject to emit the current game state, and any components that need to know the current state can subscribe to the BehaviorSubject and immediately receive the current value, in addition to any subsequent changes.
Language settings: You can use a BehaviorSubject to keep track of language settings in your application. For example, you might have a service that loads a set of localized strings based on the user's preferred language. You can use a BehaviorSubject to emit the current language to each component that is subscribed to it. When the user changes the selected language all subscribed components get notified and can act accordingly.
Manage the state of data sets: For example, if you have a warehouse application where you display the state of the locations in the warehouse, you can use the BehaviorSubject to hold the current state of the locations. Now all components that need this state can subscribe to the BehaviorSubject and receive the values and any subsequent changes to it.
NOTE: If you use BehaviorSubject to manage state its important to know that the data emitted (and held) by the BehaviorSubject is not immutable by itself.
It's possible to use the BehaviorSubject to manage your global application state, but if you emit reference objects like arrays and objects they are not immutable by default. So changing the values in one place will change the reference object in other places as well. This can cause some nasty bugs that are quite hard to locate. If you want to use the BehaviorSubject for state management it's recommended to make the emitted value immutable by using Object.Freeze, structuredClone, or some other method to make a deep clone of the data you emit.
Now you have some context and examples let's compare the two with bullet points; RxJS Subject vs BehaviorSubject
Subject:
Initialized without an initial value
Only emits new values to subscribers, starting from the moment of subscription
Good for event-driven architecture
Good for reacting to user interaction across multiple components
BehaviorSubject:
Is initialized with an initial value
Subscribers receive the most recently emitted value and then all future emitted values
Suited for managing stateful data streams
Can be used for global state management, but if you do so make sure to make the emitted values immutable
Conclusion
Both RxJS Subject and BehaviorSubject are powerful tools for managing data streams and communication between components in your application. While both classes can be used to emit data to subscribers, they have some key differences that make them better suited for different use cases.
RxJS Subject is a simple and lightweight way to publish and subscribe to events, making it a good choice for event-driven architectures, pub/sub patterns, and handling user interactions. However, it does not keep track of the current value, so new subscribers will not receive the most recent value.
RxJS BehaviorSubject, on the other hand, keeps track of the current value and emits it to new subscribers when they first subscribe. This makes it a good choice for managing stateful data streams, such as user authentication status, game state, localization settings, and API response caching.
When deciding which to use, consider the type of data you need to manage and whether you need to keep track of the current value. In some cases, a Subject might be the best choice, while in others, a BehaviorSubject might be more appropriate. Ultimately, by understanding the differences between these two RxJS classes, you can choose the one that best meets your needs and helps you to achieve what you're seeking to do.