Data & FormsExtra· 45 min read

RxJS & Observables: Angular’s Reactive Heart

An Observable is a stream of values that arrive over time — and almost everything async in Angular (HTTP, the router, forms) hands you one.

What you will learn

  • Explain what an Observable is and how it differs from a single value
  • Subscribe and unsubscribe correctly
  • Reshape a stream with map, filter and the async pipe

A value that arrives over time

You already know a normal value: it is there right now (name = "Asha"). An Observable is different — it is a stream: zero, one, or many values that arrive over time. Think of a normal value as a single letter in your hand, and an Observable as a mailbox that may receive letters now, in a second, or never.

RxJS is the library Angular uses to work with these streams (the name means “Reactive Extensions for JavaScript”). You cannot avoid it: HttpClient returns an Observable, the router gives route changes as an Observable, and reactive forms report value changes as an Observable. Learning RxJS is what lets you read and write real Angular code.

A normal valueAn Observable
When you get itRight nowLater, possibly many times
How many valuesExactly oneZero, one, or many over time
How you read itJust use itYou subscribe to it
Examplesa string, a numberan HTTP reply, clicks, a timer

Subscribe to listen to the stream

An Observable does nothing until you subscribe — that is like opening your mailbox to start receiving letters. The function you pass runs each time a value arrives.

of(...) builds a small Observable; subscribe listens
// a simple stream that emits three numbers
import { of } from 'rxjs';

const numbers = of(1, 2, 3);

numbers.subscribe(value => {
  console.log('Got:', value);
});

Note: Output: Got: 1 Got: 2 Got: 3 of(1, 2, 3) makes an Observable that emits those values in order. subscribe runs the function once per value, so we see three lines. Without subscribe, nothing would happen at all.

Reshape the stream with operators

An operator is a tool that transforms a stream as values pass through, inside a .pipe(...). The two you will meet first are map (change each value) and filter (keep only some). They mirror the array methods you already know — but they work on values arriving over time.

filter then map inside a pipe
import { of } from 'rxjs';
import { map, filter } from 'rxjs/operators';

of(1, 2, 3, 4)
  .pipe(
    filter(n => n % 2 === 0),   // keep evens
    map(n => n * 10)            // multiply each by 10
  )
  .subscribe(v => console.log(v));

Note: Output: 20 40 The stream 1,2,3,4 first passes through filter (only 2 and 4 survive), then through map (×10), giving 20 and 40. Operators run left to right, each handing its result to the next.

Subjects: streams you push values into

Sometimes you want to create a stream and push values into it yourself — for example, to share live data between components. A Subject is an Observable you can also feed. A BehaviorSubject is the same but remembers its latest value and gives it to anyone who subscribes — perfect for current state like “the logged-in user”.

A BehaviorSubject holds and emits a current value
import { BehaviorSubject } from 'rxjs';

const count = new BehaviorSubject(0);   // starts holding 0

count.subscribe(v => console.log('A sees', v));
count.next(1);                          // push a new value
count.next(2);

Note: Output: A sees 0 A sees 1 A sees 2 The subscriber immediately gets the current value (0), then every new value pushed with next(...). This is the simplest way to share changing state across an app from a service.

The async pipe: subscribe for you

Subscribing by hand means you must also unsubscribe later (in ngOnDestroy) or risk a memory leak. Angular’s async pipe does both for you: it subscribes when the template needs the value and unsubscribes automatically when the component is destroyed.

A stream that ticks every second
// component class
import { interval } from 'rxjs';
export class TimerComponent {
  seconds$ = interval(1000);   // emits 0,1,2,3… every second
}
The async pipe handles subscribe/unsubscribe
<!-- template: the async pipe subscribes and cleans up -->
<p>Seconds passed: {{ seconds$ | async }}</p>

Note: Output: Seconds passed: 0 (then 1, 2, 3… every second) The | async pipe subscribes to seconds$, shows each value, and unsubscribes when the component leaves — no manual cleanup. The $ on the end of the name is a common convention meaning “this is an Observable”.

Watch out: When you subscribe by hand (not via the async pipe), you must unsubscribe in ngOnDestroy, or the subscription keeps running after the component is gone — a memory leak. The async pipe avoids this entirely, so prefer it when you can.

Tip: A useful first set of operators: map (transform), filter (keep some), debounceTime (wait until typing pauses — great for search boxes), and switchMap (swap to a new inner stream, e.g. fire a new HTTP call per keystroke and cancel the old one).

Q. What is the key difference between a normal value and an Observable?

Answer: A normal value exists now; an Observable is a stream that emits zero, one, or many values over time, and you subscribe to listen. HttpClient, the router and reactive forms all return Observables.

✍️ Practice

  1. Use of(10, 20, 30) and subscribe to log each value.
  2. Pipe a stream through map to double every value, then log the results with the async pipe in a template.

🏠 Homework

  1. Create a BehaviorSubject in a service that holds a message string, update it with next(...) from a button, and display it in two different components using the async pipe.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →