Chapter 9.5โ˜• 15 min read

Subjects

Subjects are both Observable and Observer. They are the foundation of multicasting and state management in Angular services.

01What is a Subject

A Subject is a special type of Observable that is BOTH an Observable (you can subscribe) AND an Observer (you can push values).

"Subject = announcement speaker โ€” you can listen AND you can speak."

import { Subject } from 'rxjs';

// Create a Subject
const notification$ = new Subject();

// Subscribe to it (like Observable)
notification$.subscribe(msg => console.log('Listener 1:', msg));

// Push values to it (like Observer)
notification$.next('๐Ÿ— Biryani ready!');
// Listener 1: ๐Ÿ— Biryani ready!

// Late subscribers miss previous values
notification$.next('๐Ÿฅ˜ New curry added!');
// Listener 1: ๐Ÿฅ˜ New curry added!
// New subscriber below MISSES "Biryani ready!"
notification$.subscribe(msg => console.log('Listener 2:', msg));

Key facts about Subjects:

  • Used for cross-component communication (service โ†’ multiple components)
  • Multicast โ€” one Subject, many subscribers share same execution
  • New subscribers miss previous values (except BehaviorSubject/ReplaySubject)
  • Don't forget to complete() when done to avoid memory leaks
02Subject โ€” Basic

Subject is the basic type โ€” no replay, no initial value. New subscribers only get values emitted AFTER they subscribe.

import { Subject } from 'rxjs';

const subject = new Subject();

// Late subscriber โ€” misses 1 and 2
setTimeout(() => {
  subject.subscribe(v => console.log('Late:', v)); // Only sees 3
}, 1000);

subject.next(1);
subject.next(2);
setTimeout(() => subject.next(3), 2000);

"Subject = live radio โ€” jo abhi bol rahe wo sunao, purana nahi."

Use cases for Subject:

  • Event bus for one-time notifications
  • Button click events, form submit events
  • Any "fire and forget" event where history doesn't matter

โš ๏ธ Best practice: Always expose Subject as Observable to prevent external code from calling .next():

private refreshSubject = new Subject();

// Public as Observable only โ€” components can subscribe but not emit
refresh$ = this.refreshSubject.asObservable();

// Only this service can call next()
triggerRefresh() {
  this.refreshSubject.next();
}
03BehaviorSubject โ€” Has Current Value

BehaviorSubject is the most used Subject type. It requires an initial value and replays the LAST value to new subscribers.

import { BehaviorSubject } from 'rxjs';

// REQUIRES initial value
const userSubject = new BehaviorSubject(null);

// Subscribe immediately gets current value
userSubject.subscribe(user => console.log('User:', user));
// Output: User: null (initial value)

// Push a new value
userSubject.next({ id: 1, name: 'Shaik' });
// Output: User: { id: 1, name: 'Shaik' }

// New subscriber gets LAST value immediately
setTimeout(() => {
  userSubject.subscribe(user => console.log('Late:', user));
  // Output: Late: { id: 1, name: 'Shaik' } โ€” gets latest immediately!
}, 5000);

"BehaviorSubject = DVR โ€” join late bhi ho, last episode dikh jayega."

Why BehaviorSubject is the MOST USED Subject in Angular:

  • All components always have the current state โ€” even if they subscribe late
  • Initial value prevents "undefined" errors
  • .getValue() โ€” get current value synchronously (for imperative use)

BehaviorSubject is the foundation of the service state management pattern in Angular.

04ReplaySubject โ€” Replay N Values

ReplaySubject replays a configurable number of past values to new subscribers.

import { ReplaySubject } from 'rxjs';

// ReplaySubject(bufferSize) โ€” replay last N values
const chatMessages$ = new ReplaySubject(3); // Replay last 3

chatMessages$.next('Hello');
chatMessages$.next('Kya haal hai?');
chatMessages$.next('Biryani khao?');
chatMessages$.next('Chalo khaate hain!');

// New subscriber gets last 3 messages
chatMessages$.subscribe(msg => console.log(msg));
// Output: 'Kya haal hai?', 'Biryani khao?', 'Chalo khaate hain!'

"ReplaySubject = highlights reel โ€” last 3 moments dikhao."

Use cases for ReplaySubject:

  • Chat message history
  • Audit logs
  • Notification feed (last N items)
  • Any scenario where late subscribers should see recent history

With Infinity buffer: new ReplaySubject(Infinity) โ€” replays ALL past values (use carefully, memory grows unbounded).

05AsyncSubject โ€” Last Value Only After Complete

AsyncSubject emits ONLY the LAST value, and ONLY AFTER complete() is called.

import { AsyncSubject } from 'rxjs';

const result$ = new AsyncSubject();

result$.subscribe(v => console.log('Result:', v));
// No output yet โ€” still waiting for complete()

result$.next(1);
result$.next(2);
result$.next(42); // This will be the LAST value

// Nothing emitted yet! No complete() called

result$.complete();
// NOW output: Result: 42 (only the LAST value)

"AsyncSubject = exam result โ€” sab wait karo, result ek baar aayega."

Rarely used in Angular โ€” but good to know.

Use cases: Result of a computation that runs once and completes (like a Promise alternative).

Subject types comparison:

Subject          โ€” No replay, no initial value
BehaviorSubject  โ€” Replays 1 (last value), requires initial value
ReplaySubject    โ€” Replays N (configurable), optional initial value
AsyncSubject     โ€” Replays 1 (last), but ONLY after complete()

Key Takeaways

  • โœ… Subject = BOTH Observable and Observer โ€” subscribe to listen, .next() to emit
  • โœ… Subject โ€” no replay (late subscribers miss previous values), for events/notifications
  • โœ… BehaviorSubject โ€” replays last value, REQUIRES initial value, MOST USED in Angular services
  • โœ… ReplaySubject(N) โ€” replays last N values, for chat/log history
  • โœ… AsyncSubject โ€” emits last value only after complete(), like a Promise
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase