Subject variants differ mainly in what late subscribers receive and when. Use Subject for fire-and-forget events, BehaviorSubject for current state, ReplaySubject for bounded history, and AsyncSubject for final-on-complete delivery.
Use this Angular interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
Subject vs BehaviorSubject vs ReplaySubject vs AsyncSubject in Angular: when do you use which?Frontend interview answer
This Angular interview question tests whether you can explain Subject vs BehaviorSubject vs ReplaySubject vs AsyncSubject: late subscribers and state rules, connect it to production trade-offs, and handle common follow-up questions.
- Subject vs BehaviorSubject vs ReplaySubject vs AsyncSubject: late subscribers and state rules explanation without falling back to memorized docs wording
- RxJS and Observables reasoning, edge cases, and production failure modes
- How you would answer the most likely Angular interview follow-up
Late-subscriber decision
These Subject variants differ mainly by what late subscribers receive and when. Subject has no initial value and no replay. BehaviorSubject always has a current value. ReplaySubject replays buffered history. AsyncSubject emits only the final value after completion. Pick the wrong one and the UI either misses state, replays too much history, or never emits when you expect.
Quick matrixSubject: event bus, no history.BehaviorSubject: current state, immediate latest value.ReplaySubject: buffered history for late subscribers.AsyncSubject: final result only after completion.
Failure pattern
- Use
Subjectfor app state and late subscribers miss the current value. - Use
ReplaySubjectcarelessly and memory or history grows more than intended. - Use
AsyncSubjectfor a stream that never completes and subscribers see nothing.
Type | Initial value required? | What a late subscriber gets | Best fit |
|---|---|---|---|
| No | Only future emissions | Fire-and-forget events (click intents, toast triggers) |
| Yes | Latest value immediately | Current UI state (selected tab, auth status, filter value) |
| No | Last | History/buffer use-cases (chat stream, recent actions) |
| No | Final value only, and only after completion | One-shot workflows where only the final result matters |
import { Subject, BehaviorSubject, ReplaySubject, AsyncSubject } from 'rxjs';
// 1) Subject: event bus for "do something now" signals
const refreshClick$ = new Subject<void>();
// 2) BehaviorSubject: always has a current state value
const selectedTheme$ = new BehaviorSubject<'light' | 'dark'>('light');
// 3) ReplaySubject: keep last N values for late subscribers
const recentSearches$ = new ReplaySubject<string>(3);
// 4) AsyncSubject: emit only final value when complete() is called
const finalReport$ = new AsyncSubject<string>();
finalReport$.next('draft');
finalReport$.next('final');
finalReport$.complete(); // subscribers receive only 'final'
Scenario | Pick | Why |
|---|---|---|
Button click intent stream |
| No initial or replayed value needed |
Store current search/filter state |
| New subscribers need immediate current value |
Keep a short in-memory event history |
| Late subscribers need recent context |
Only publish final batch/job result |
| Intermediate values are noise |
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class SearchUiStore {
private readonly querySubject = new BehaviorSubject<string>('');
readonly query$ = this.querySubject.asObservable();
private readonly refreshSubject = new Subject<void>();
readonly refresh$ = this.refreshSubject.asObservable();
setQuery(value: string): void {
this.querySubject.next(value);
}
refresh(): void {
this.refreshSubject.next();
}
}
Common pitfall | Why it hurts | Fix |
|---|---|---|
Using | Consumers must handle meaningless initial states everywhere | Use |
Using large | Memory grows and old state lingers too long | Keep buffer small and intentional |
Choosing | No value is emitted because completion never happens | Use |
Exposing the Subject itself publicly | Any consumer can call | Keep Subject private and expose only |
Interview summarySubject = live events only. BehaviorSubject = current value + future updates. ReplaySubject = recent history + future updates. AsyncSubject = only final value on completion. In Angular, default to BehaviorSubject for local UI state, Subject for intent events, and ReplaySubject only when you truly need history.
Use this as one explanation rep, then continue with the Angular interview questions cluster or a guided prep path.