Skip to main content
Angular Basics
CHAPTER 19 Beginner

Angular RxJS Basics

Updated: May 18, 2026
5 min read

# CHAPTER 19

Angular RxJS Basics

1. Chapter Introduction

RxJS (Reactive Extensions for JavaScript) is the library that powers Angular's asynchronous operations — HttpClient returns Observables, Router events are Observables, form valueChanges are Observables. RxJS provides a rich set of operators to transform, filter, combine, and control data streams. Understanding RxJS transforms you from an Angular developer to an Angular architect.

2. Learning Objectives

  • Understand the Observable/Observer pattern.
  • Create Observables from scratch.
  • Use common RxJS operators: map, filter, switchMap, debounceTime.
  • Chain operators using pipe().
  • Handle errors with catchError.

3. The Observable Pattern

An Observable is a stream of data over time. Think of it as a water pipe:
  • The Observable is the pipe.
  • The Observer (your .subscribe() callback) is the tap/faucet at the end.
  • Data events flow through the pipe.
typescript
1234567891011121314151617
import { Observable, of, from, interval } from 'rxjs';

// Create an Observable that emits 3 values
const myObservable$ = new Observable<number>(observer => {
  observer.next(1);
  observer.next(2);
  observer.next(3);
  observer.complete(); // No more values
});

// Subscribe to start receiving values
myObservable$.subscribe({
  next: value => console.log(&#039;Received:&#039;, value),
  error: err => console.error(&#039;Error:&#039;, err),
  complete: () => console.log(&#039;Stream completed!&#039;)
});
// Output: Received: 1, Received: 2, Received: 3, Stream completed!

4. Creation Operators

typescript
1234567891011121314
import { of, from, interval, fromEvent } from &#039;rxjs&#039;;

// of() — emit values immediately
of(1, 2, 3).subscribe(v => console.log(v));

// from() — emit each element of an array or Promise
from([10, 20, 30]).subscribe(v => console.log(v));
from(fetch(&#039;/api/users&#039;)).subscribe(); // Converts Promise to Observable

// interval() — emit incrementing number every N milliseconds
interval(1000).subscribe(i => console.log(&#039;Tick:&#039;, i)); // 0, 1, 2...

// fromEvent() — DOM events as Observables
fromEvent(document, &#039;click&#039;).subscribe(event => console.log(&#039;Clicked!&#039;, event));

5. The pipe() Method and Operators

Operators are functions applied inside pipe() that transform the stream without modifying the original Observable.
typescript
1234567891011
import { of } from &#039;rxjs&#039;;
import { map, filter, take } from &#039;rxjs/operators&#039;;

of(1, 2, 3, 4, 5, 6)
  .pipe(
    filter(n => n % 2 === 0),   // Keep only even: 2, 4, 6
    map(n => n * 10),           // Multiply by 10: 20, 40, 60
    take(2)                     // Only take 2 values: 20, 40
  )
  .subscribe(result => console.log(result));
// Output: 20, 40

6. Essential Operators for Angular

#### map — Transform each value

typescript
123
this.http.get<any[]>(&#039;/api/products&#039;).pipe(
  map(products => products.filter(p => p.inStock))
).subscribe(inStockProducts => this.products = inStockProducts);

#### switchMap — Cancel previous request, make new one (perfect for search)

typescript
12345
this.searchInput.valueChanges.pipe(
  debounceTime(300),                          // Wait 300ms after user stops typing
  distinctUntilChanged(),                     // Only if value actually changed
  switchMap(term => this.apiService.search(term)) // Cancel old, start new request
).subscribe(results => this.results = results);

#### debounceTime — Delay emissions (for search inputs) #### distinctUntilChanged — Ignore duplicate consecutive values #### mergeMap — Like switchMap but doesn't cancel previous requests #### forkJoin — Combine multiple Observables, emit when ALL complete

typescript
123456789
import { forkJoin } from &#039;rxjs&#039;;

// Make two API calls simultaneously, wait for both
forkJoin({
  user: this.http.get(&#039;/api/user/1&#039;),
  products: this.http.get(&#039;/api/products&#039;)
}).subscribe(({ user, products }) => {
  console.log(&#039;Both loaded:&#039;, user, products);
});
search.component.ts
123456789101112131415161718192021222324252627
import { Component, OnInit } from &#039;@angular/core&#039;;
import { FormControl } from &#039;@angular/forms&#039;;
import { debounceTime, distinctUntilChanged, switchMap } from &#039;rxjs/operators&#039;;

@Component({
  selector: &#039;app-search&#039;,
  template: `
    <input [formControl]="searchCtrl" placeholder="Search products..." />
    <ul>
      <li *ngFor="let result of results">{{ result.name }}</li>
    </ul>
  `
})
export class SearchComponent implements OnInit {
  searchCtrl = new FormControl(&#039;&#039;);
  results: any[] = [];

  constructor(private productService: ProductService) {}

  ngOnInit(): void {
    this.searchCtrl.valueChanges.pipe(
      debounceTime(400),
      distinctUntilChanged(),
      switchMap(term => this.productService.search(term || &#039;&#039;))
    ).subscribe(results => this.results = results);
  }
}

8. Common Mistakes

  • Nested subscribes: Never subscribe inside a subscribe. Use switchMap or mergeMap instead.
  • Not completing Observables: interval() and fromEvent() run forever. Always use takeUntilDestroyed() or take(N) to limit them.

9. MCQs with Answers

Question 1

What is an RxJS Observable?

Question 2

What method starts receiving values from an Observable?

Question 3

What method is used to chain RxJS operators on an Observable?

Question 4

Which operator transforms each emitted value into a new value?

Question 5

Which operator keeps only values that match a condition?

Question 6

Which operator is ideal for a live search input — cancels the previous HTTP request when a new search term arrives?

Question 7

What does debounceTime(300) do?

Question 8

What does distinctUntilChanged() do?

Question 9

What does forkJoin do?

Question 10

What is "nested subscribe" and why is it bad?

10. Interview Questions

  • Q: Explain the difference between switchMap, mergeMap, and concatMap.
  • Q: Why would you use forkJoin instead of multiple sequential API calls?

11. Summary

RxJS is the functional, reactive programming backbone of Angular. By mastering a handful of operators — map, filter, switchMap, debounceTime — you can handle virtually any asynchronous scenario in a declarative, readable, and composable way. These patterns significantly outperform nested promises and callbacks.

12. Next Chapter Recommendation

In Chapter 20: Observables and Subjects, we go deeper into RxJS Subjects — Subject, BehaviorSubject, ReplaySubject — and learn how to use the async pipe to elegantly manage subscriptions in templates.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·