Core Concepts of Subject
Subject is a special type of Observable in RxJS that is both an Observable and an Observer. This means it can:
- Be subscribed to by multiple observers
- Actively push new values to all subscribers
- Implement multicast functionality
Subject Types
1. Subject
Basic Subject, does not replay previous values when new subscribers arrive
javascriptconst subject = new Subject(); subject.next(1); subject.next(2); const subscription1 = subject.subscribe(value => console.log('Subscriber 1:', value)); // Subscriber 1: 3 // Subscriber 1: 4 subject.next(3); subject.next(4); const subscription2 = subject.subscribe(value => console.log('Subscriber 2:', value)); // Subscriber 2: 5 // Subscriber 2: 6 subject.next(5); subject.next(6);
2. BehaviorSubject
BehaviorSubject remembers the latest value, new subscribers immediately receive the current value
javascriptconst behaviorSubject = new BehaviorSubject('initial value'); behaviorSubject.subscribe(value => console.log('Subscriber 1:', value)); // Subscriber 1: initial value behaviorSubject.next('value 1'); // Subscriber 1: value 1 behaviorSubject.subscribe(value => console.log('Subscriber 2:', value)); // Subscriber 2: value 1 - immediately receives latest value behaviorSubject.next('value 2'); // Subscriber 1: value 2 // Subscriber 2: value 2
3. ReplaySubject
ReplaySubject can replay a specified number of historical values
javascriptconst replaySubject = new ReplaySubject(2); // Replay last 2 values replaySubject.next('value 1'); replaySubject.next('value 2'); replaySubject.next('value 3'); replaySubject.subscribe(value => console.log('Subscriber 1:', value)); // Subscriber 1: value 2 // Subscriber 1: value 3 replaySubject.next('value 4'); // Subscriber 1: value 4 replaySubject.subscribe(value => console.log('Subscriber 2:', value)); // Subscriber 2: value 3 // Subscriber 2: value 4
4. AsyncSubject
AsyncSubject only emits the last value upon completion
javascriptconst asyncSubject = new AsyncSubject(); asyncSubject.subscribe(value => console.log('Subscriber 1:', value)); asyncSubject.next('value 1'); asyncSubject.next('value 2'); asyncSubject.next('value 3'); // No output yet asyncSubject.complete(); // Subscriber 1: value 3 - only emits the last value asyncSubject.subscribe(value => console.log('Subscriber 2:', value)); // Subscriber 2: value 3 - new subscribers also receive the last value
Practical Use Cases
Subject Use Cases
- Event bus
- State management
- Sharing data streams across multiple components
BehaviorSubject Use Cases
- Storing current state
- Form state management
- User information management
ReplaySubject Use Cases
- Caching historical data
- Replaying operation logs
- Error retry mechanisms
AsyncSubject Use Cases
- HTTP request caching
- Calculations that only need the final result
- Last value of asynchronous operations
Difference from Regular Observable
javascript// Regular Observable - unicast const observable = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); }); observable.subscribe(v => console.log('Observer 1:', v)); observable.subscribe(v => console.log('Observer 2:', v)); // Each subscriber executes independently // Subject - multicast const subject = new Subject(); const source = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); }); source.subscribe(subject); subject.subscribe(v => console.log('Subscriber 1:', v)); subject.subscribe(v => console.log('Subscriber 2:', v)); // All subscribers share the same data stream
Performance Considerations
Subject can improve performance in multicast scenarios by avoiding duplicate execution of the same asynchronous operations. However, be mindful of memory leaks and unsubscribe in a timely manner.