← Back to Articles         
RxJS & Observables - Interview Question

RxJS & Observables - Interview Question

Published on 12 Oct 2026     5 min read Angular
Quick Revision
 

Group 13: RxJS & Observables — Interview Quick Revision

1. What is RxJS?

RxJS (Reactive Extensions for JavaScript) is a library for handling asynchronous and event-based operations using Observables. Angular uses RxJS for HTTP requests, reactive forms, and event handling.

2. What is an Observable?

An Observable represents a stream of values emitted over time. It can emit multiple values, complete, or produce an error.

const numbers$ = of(1, 2, 3);
numbers$.subscribe(x => console.log(x));

3. Why does Angular HttpClient return Observables?

Angular HttpClient returns Observables to support asynchronous execution, cancellation, error handling, and RxJS operators. HTTP requests execute when subscribed to.

4. Observable vs Promise — what is the difference?

Observable

Promise

Can emit multiple values

Resolves once

Lazy execution

Eager execution

Supports operators

Uses .then() / await

Supports cancellation via unsubscribe

No built-in cancellation

5. What is subscribe()?

subscribe() starts listening to an Observable and handles emitted values, errors, and completion. It returns a Subscription that can be unsubscribed.

this.http.get('/api/users').subscribe(data => console.log(data));

6. What are RxJS operators?

RxJS operators are functions used to transform, filter, combine, or handle Observable streams. Common operators include map, filter, switchMap, tap, and catchError.

of(1, 2, 3).pipe(map(x => x * 2)).subscribe(console.log);

7. What does map() do?

map() transforms each emitted value into another value. It is commonly used to modify API response data.

of(1, 2, 3).pipe(map(x => x * 10)).subscribe(console.log);
// Output: 10, 20, 30

8. What does filter() do?

filter() allows only values that satisfy a condition to pass through the Observable stream.

of(1, 2, 3, 4).pipe(filter(x => x > 2)).subscribe(console.log);
// Output: 3, 4

9. What does tap() do?

tap() performs side effects such as logging or debugging without modifying the emitted values.

of(1, 2).pipe(tap(x => console.log('Log:', x))).subscribe();

10. What does catchError() do?

catchError() handles errors in an Observable stream and returns a replacement Observable or rethrows the error. It is commonly used for HTTP error handling.

this.http.get('/api/users').pipe(
  catchError(err => { console.error(err); return of([]); })
);

11. What does switchMap() do?

switchMap() switches to a new inner Observable and unsubscribes from the previous one when a new value arrives. It is useful for search autocomplete.

search$.pipe(switchMap(term => this.http.get(`/api/search?q=${term}`)));

12. What does mergeMap() do?

mergeMap() executes multiple inner Observables concurrently without cancelling previous operations. It is useful for independent API requests.

ids$.pipe(mergeMap(id => this.http.get(`/api/users/${id}`)));

13. What does concatMap() do?

concatMap() executes inner Observables sequentially, waiting for one to complete before starting the next. It is useful when API execution order matters.

ids$.pipe(concatMap(id => this.http.post('/api/process', { id })));

14. What does exhaustMap() do?

exhaustMap() ignores new source emissions while the current inner Observable is running. It is useful for preventing duplicate form submissions.

submit$.pipe(exhaustMap(data => this.http.post('/api/save', data)));

15. switchMap vs mergeMap — what is the difference?

switchMap

mergeMap

Cancels previous inner subscription

Keeps previous inner subscriptions

Latest request takes priority

Requests execute concurrently

Best for search/autocomplete

Best for independent API calls

Key Point: Use switchMap for latest-only requests and mergeMap when all requests must be processed.

16. What is forkJoin()?

forkJoin() executes multiple Observables and emits their last values together after all complete. It is commonly used for parallel HTTP requests.

forkJoin({ users: this.http.get('/api/users'), roles: this.http.get('/api/roles') })
  .subscribe(result => console.log(result));

17. What is combineLatest()?

combineLatest() combines the latest values from multiple Observables and emits whenever any source changes, after every source has emitted at least once.

combineLatest([of(10), of(20)]).subscribe(console.log);
// Output: [10, 20]

18. What is a Subject?

A Subject is a special Observable that can both emit values and be subscribed to. It supports multicasting, allowing multiple subscribers to receive the same emissions.

const subject = new Subject<number>();
subject.subscribe(console.log); subject.next(10);

19. What is a BehaviorSubject?

A BehaviorSubject is a Subject that requires an initial value and stores the latest emitted value. New subscribers immediately receive the current value.

const user$ = new BehaviorSubject<string>('Guest');
user$.next('Admin');

20. Subject vs BehaviorSubject — what is the difference?

Subject

BehaviorSubject

No initial value required

Initial value required

Does not replay previous values

Replays latest value

No current-value getter

Supports getValue()

Useful for events

Useful for shared state

21. What is AsyncPipe?

AsyncPipe automatically subscribes to an Observable or Promise and displays its latest value in the template. It also handles subscription cleanup automatically.

@if (users$ | async; as users) {
  <p>{{ users.length }} users</p>
}

22. How do you prevent subscription memory leaks?

Use AsyncPipe, takeUntilDestroyed(), or manual unsubscribe() to clean up long-running subscriptions. Completed HttpClient requests generally do not require manual unsubscription.

this.service.getData().pipe(takeUntilDestroyed(this.destroyRef))
  .subscribe(data => console.log(data));

23. What is takeUntilDestroyed()?

takeUntilDestroyed() is an Angular RxJS interop operator that automatically completes a subscription when the component or service is destroyed.

private destroyRef = inject(DestroyRef);
this.data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe();
 

Important Interview Revision Points

Concept

Key Point

RxJS

Reactive programming library

Observable

Asynchronous data stream

subscribe()

Listen to Observable values

map()

Transform values

filter()

Filter emitted values

tap()

Logging and side effects

catchError()

Handle errors

switchMap()

Latest inner Observable only

mergeMap()

Concurrent execution

concatMap()

Sequential execution

exhaustMap()

Ignore new emissions while busy

forkJoin()

Wait for all to complete

combineLatest()

Combine latest emitted values

Subject

Multicast event stream

BehaviorSubject

Holds latest value

AsyncPipe

Automatic subscription management

takeUntilDestroyed()

Automatic cleanup on destruction

Interview priority: Focus particularly on questions 2, 3, 4, 5, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, and 23.

For an Angular + ASP.NET Core Full Stack Developer interview, the most important practical scenarios are using switchMap() for API-based searching, forkJoin() for parallel API calls, catchError() for API failures, and takeUntilDestroyed() for subscription cleanup.

← Back to Articles