Angular

RxJS Operators for Angular Interviews: switchMap, mergeMap, concatMap and More

8 min read R Square IT Support TeamSample article

The RxJS operators Angular interviewers ask about most — when to use each flattening operator, how to avoid memory leaks, and how to handle errors without breaking a stream.

Angular uses RxJS for HTTP calls, router events and reactive forms, so interviewers expect you to know the common operators and — more importantly — when to choose one over another.

1. What is the difference between switchMap, mergeMap, concatMap and exhaustMap?

All four map each value to an inner Observable and flatten the result. They differ in what happens when a new value arrives while an inner Observable is still running.

  • switchMap — cancels the previous inner Observable. Best for search-as-you-type and route parameter changes.
  • mergeMap — runs all inner Observables in parallel. Best for independent requests where order does not matter.
  • concatMap — queues them and runs one at a time, in order. Best for saving changes that must happen in sequence.
  • exhaustMap — ignores new values until the current one completes. Best for a submit or login button that should not fire twice.
typescript
this.results$ = this.searchControl.valueChanges.pipe(
  debounceTime(300),          // wait for the user to pause typing
  distinctUntilChanged(),     // skip if the text did not change
  filter((q) => q.length >= 2),
  switchMap((q) => this.api.search(q)), // cancel the previous request
);

2. How do you avoid memory leaks with subscriptions?

Subscriptions that outlive a component keep running and hold references in memory. The cleanest options are the async pipe, which subscribes and unsubscribes automatically, and takeUntilDestroyed() from @angular/core/rxjs-interop for subscriptions in code.

typescript
constructor() {
  this.route.paramMap
    .pipe(takeUntilDestroyed()) // completes when the component is destroyed
    .subscribe((params) => this.load(params.get('id')));
}

3. forkJoin vs combineLatest

  • forkJoin — waits for every Observable to complete, then emits the last values once. Ideal for loading several HTTP calls in parallel.
  • combineLatest — emits whenever any input emits (after each has emitted at least once). Ideal for combining filters, form values or state.

4. How do you handle errors without killing the stream?

An error completes an Observable. If you catch it on the outer stream, a search box stops working after the first failed request. Catch it inside the inner Observable instead, and return a fallback value.

typescript
switchMap((q) =>
  this.api.search(q).pipe(
    catchError(() => of([])), // the outer stream keeps working
  ),
)

5. What does shareReplay do?

shareReplay shares one subscription between multiple subscribers and replays the latest value(s) to late subscribers. It is commonly used to cache an HTTP response, such as configuration or the current user. Use shareReplay({ bufferSize: 1, refCount: true }) when the source should stop once nobody is listening.

6. Observables vs Signals — when to use which?

Signals are great for synchronous UI state that templates read. Observables remain the better fit for asynchronous events over time — HTTP, WebSockets, debounced input. Angular connects them with toSignal() and toObservable(), and a strong answer explains that they complement each other.

Interview tip: how should you answer “which operator would you use?”

State the behaviour you need first (cancel, parallel, queue or ignore), then name the operator. That shows you understand the concept, not just the name.

  • RxJS
  • Angular
  • Observables
  • Interview Questions

This is a sample article published as a starter resource. Verify technical details against official documentation for the versions you use.

Prepare. Perform. Progress.

Want personal guidance on this topic?

Our team can help you prepare, solve doubts and practise interviews around what you are learning.

Chat with us