Different type of Subjects in Rxjs  (used in Angular)

  • Subject
  • BehaviorSubject
  • ReplaySubject
  • AsyncSubject

 

 

 

Subject

  • A plain Subject does not hold the current/last value.
  • It emits values only to subscribers at the time of emission (not future ones).
  • Used for event emitters or multicast observables.

A standard Subject behaves similarly to a regular Observable in that a new Subscriber only receives values emitted after it subscribes.

 

iimport { Subject } from 'rxjs';

const subject = new Subject<number>();

 

// Subscriber 1
subject.subscribe(data => console.log('Subscriber 1:', data));
subject.next(1);  // Emit only next called
subject.next(2);

 

// Subscriber 2 (subscribes after some values have been emitted)
setTimeout(() => {
 subject.subscribe(data => console.log('Subscriber 2:', data));
 subject.next(3);   // Send/Emit 3 to all subscribers so far
}, 100);

 

// Output:
// Subscriber 1: 1
// Subscriber 1: 2

// Subscriber 1: 3    //First users get the Latest Value only
// Subscriber 2: 3   //Second user will get Latest Value only
 

Both User/Subscribe now see only the last/latest value

Use Case
Good for storing and accessing state, like current user or auth status.
Ideal for scenarios where you want to broadcast new events or data to multiple listeners simultaneously, and each listener only needs to know about the events happening from the moment they subscribe. 
    
Example: 
Imagine a simple chat application where new messages are broadcast to all connected users. A Subject would be suitable here, as a newly joined user only needs to see messages sent after they've logged in.

 

 

 

BehaviorSubject
it immediately receives the last emitted value (the current value) and then continues to receive any old/subsequent values. You need to provide an initial value when creating a BehaviorSubject. It doesn't get any of the previously emitted values.

Subscribers get the current/last value upon subscription and subsequent emissions.

 

import { BehaviorSubject } from 'rxjs';

const behaviorSubject = new BehaviorSubject<string>('Initial Value');

 

// Subscriber 1
behaviorSubject.subscribe(data => console.log('Subscriber 1:', data));
behaviorSubject.next('First Update'); // Emit only next called

 

// Subscriber 2 (subscribes later)
behaviorSubject.subscribe(data => console.log('Subscriber 2:', data));
behaviorSubject.next('Second Update'); // Send/Emit 'Second Update' to all subscribers so far

 

// Output:
// Subscriber 1: Initial Value- Show  welcome message to first user who join
// Subscriber 1: First Update- Show value input value added by 1st User


// Subscriber 2: First Update     //Show first the last emitted value to new user/subscriber. value imputed by previous users first.
// Subscriber 1: Second Update  // First  user will get latest value input by 2nd User
// Subscriber 2: Second Update  // Second user will get the latest value input by him


Use Cases: 
Excellent for representing state that needs to be immediately available to new subscribers. Think of it as a setting or a piece of data that always has a current state.
    
Example: 
Managing the current user's login status in an application. New components that load need to know immediately if the user is logged in or not.

 

 


ReplaySubject
it store and receives a buffer of previously emitted values. You can configure the size of this buffer (how many past values to replay) and optionally a window of time within which values should be replayed. Emits the last N values to new subscribers.

stores a buffer of previously emitted values. When a new Subscriber subscribes, it immediately receives some or all of the values from the buffer, depending on how the ReplaySubject was configured (buffer size and optional time window). a ReplaySubject does indeed emit the buffered values to a new Subscriber at the moment of subscription

import { ReplaySubject } from 'rxjs';

 

// You created a ReplaySubject that is configured to store and replay the last two emitted values.
const replaySubject = new ReplaySubject<number>(2);

 

// The value 1 is emitted and stored in the ReplaySubject's internal buffer. The buffer now contains [1].
replaySubject.next(1);


//The value 2 is emitted and added to the buffer. Since the buffer size is 2, the oldest value (1) is shifted out. The buffer now contains [2]
replaySubject.next(2);


// The value 3 is emitted and added to the buffer. Again, the oldest value (2) is shifted out. The buffer now contains [3]
replaySubject.next(3);


Subscriber 1 subscribes. Because it's a ReplaySubject with a buffer of 2, Subscriber 1 immediately receives the current contents of the buffer, which are 2 and then 3. Then, it receives 4 when it's emitted.
replaySubject.subscribe(data => console.log('Subscriber 1:', data));

 

The value 4 is emitted and added to the buffer. The oldest value (3) is shifted out. The buffer now contains [4]. Subscriber 1 receives this value.
replaySubject.next(4);

 

// After a delay, Subscriber 2 subscribes.
setTimeout(() => {
 replaySubject.subscribe(data => console.log('Subscriber 2:', data));
}, 100);

// When Subscriber 2 subscribes, the ReplaySubject immediately replays the current contents of its buffer, which at this point are the last two emitted values: 3 and then 4.

// Therefore, Subscriber 2 received 3 and 4 upon subscription because the ReplaySubject was configured to remember and replay the last two emitted values,

 

// Output:
// Subscriber 1: 2  // 1st users is subscribed Emit 1st from last 2 values 
// Subscriber 1: 3 // 1st users is subscribed Emit 2nd from last 2 values 
// Subscriber 1: 4 // 1st users is subscribed Emit his own value

 

// a ReplaySubject does indeed emit the buffered values to a new Subscriber at the moment of subscription
// Subscriber 2: 3
// Subscriber 2: 4

 

Use Cases: 
Useful when you have events or data that new subscribers need to catch up on. Think of it like a log or a history of events.
    
Example: 
Caching API responses or replaying a sequence of user actions for a new component that needs to initialize its state.

 

 

AsyncSubject: 
This is a special type of Subject that only emits the last value to its Observers when it completes. Emits only the last value upon completion, and only to subscribers at that point. 

At that point, all subscribers will receive the very last value that was emitted before completion. If no value was emitted before completion, the subscribers receive nothing.

import { AsyncSubject } from 'rxjs';

const asyncSubject = new AsyncSubject<string>();

 

// Subscriber 1
asyncSubject.subscribe(data => console.log('Subscriber 1:', data));

asyncSubject.next('First Value');
asyncSubject.next('Second Value');

 

// Subscriber 2 (subscribes later)
setTimeout(() => {
 asyncSubject.subscribe(data => console.log('Subscriber 2:', data));
 asyncSubject.complete(); // Only when complete() is called do subscribers receive the last value
}, 100);

 

// Output (after 100ms):  // All Current subscribe will receive the last value
// Subscriber 1: Second Value
// Subscriber 2: Second Value

 

Use Cases: 
Useful for scenarios where you are interested in the final result of an asynchronous operation. Think of it like waiting for a process to finish and then getting its final output.


Example: 
Representing the result of an HTTP request that completes after fetching data

 


Related Question