Skip to content
beginner Phase 10 · RxJS Operators for Angular

Observables and Subscriptions

Create streams, subscribe to them, and clean up correctly.

40m
0 problems
Topic Progress 0%

Creating and Subscribing to Observables

An Observable is a stream that emits zero or more values over time, then completes or errors.

Creating an Observable

import { Observable } from 'rxjs';

const numbers$ = new Observable<number>(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  subscriber.complete();
});

Subscribing

const subscription = numbers$.subscribe({
  next: value => console.log('Value:', value),
  error: err => console.error('Error:', err),
  complete: () => console.log('Complete'),
});

// Output:
// Value: 1
// Value: 2
// Value: 3
// Complete

Unsubscribing

const subscription = numbers$.subscribe(value => console.log(value));

// Later, to stop receiving values
subscription.unsubscribe();

Cold vs Hot Observables

Type Behavior Example
Cold Each subscriber gets its own independent stream HttpClient, of(), from()
Hot All subscribers share the same stream Subjects, DOM events, WebSockets
// Cold — each subscriber triggers the producer
const cold$ = new Observable(subscriber => {
  console.log('Producer executed');
  subscriber.next(Math.random());
});

cold$.subscribe(v => console.log('A:', v)); // Producer executed, A: 0.123
cold$.subscribe(v => console.log('B:', v)); // Producer executed, B: 0.456

// Hot — producer runs once, all subscribers share
const hot$ = new Subject<number>();
hot$.subscribe(v => console.log('A:', v));
hot$.subscribe(v => console.log('B:', v));

hot$.next(42); // A: 42, B: 42 (same value)

Cleanup and Memory Leak Prevention

Subscriptions must be cleaned up to prevent memory leaks. Angular provides several mechanisms.

Manual Unsubscribe

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnInit(): void {
    this.dataService.getData().pipe(
      takeUntil(this.destroy$)
    ).subscribe(data => {
      this.data = data;
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

takeUntil Operator

import { takeUntil } from 'rxjs/operators';

this.dataService.getData().pipe(
  takeUntil(this.destroy$)
).subscribe();

async Pipe (Automatic Cleanup)

<div *ngIf="data$ | async as data">
  {{ data }}
</div>

The async pipe automatically unsubscribes when the component is destroyed.

take(1) — Auto-Complete After First Emission

this.route.paramMap.pipe(
  take(1)
).subscribe(params => {
  // Only runs once
});

Common Memory Leak Patterns

// BAD: No cleanup
ngOnInit(): void {
  this.dataService.getData().subscribe(data => {
    this.data = data;
  });
}

// GOOD: takeUntil pattern
ngOnInit(): void {
  this.dataService.getData().pipe(
    takeUntil(this.destroy$)
  ).subscribe(data => {
    this.data = data;
  });
}

// GOOD: async pipe in template
data$ = this.dataService.getData();

Quiz

1. What is the difference between a cold and hot Observable?

Question 1 options

2. How do you prevent memory leaks from subscriptions?

Question 2 options

3. What does takeUntil(destroy$) do?

Question 3 options

Flashcards

Question

Cold vs Hot Observable?

Answer

Cold: per-subscriber stream (HttpClient). Hot: shared stream (Subjects).

Question

How to prevent memory leaks?

Answer

Unsubscribe in ngOnDestroy, use takeUntil, or use async pipe.

Question

What does takeUntil do?

Answer

Completes the Observable when the notifier emits, auto-unsubscribing.

Revision Notes

Key Takeaways

  • 1. Cold Observables run per subscriber; hot Observables share
  • 2. Always unsubscribe to prevent memory leaks
  • 3. takeUntil(destroy$) is the standard cleanup pattern
  • 4. async pipe handles subscription and cleanup automatically

Interview Tips

  • • Explain cold vs hot Observables
  • • Be ready to describe memory leak prevention
  • • Mention the async pipe as the preferred template pattern

Cheat Sheet

Observables and Subscriptions Cheat Sheet

Create:

new Observable(subscriber => {
  subscriber.next(value);
  subscriber.complete();
})

Subscribe:

const sub = observable$.subscribe({
  next: v => {},
  error: e => {},
  complete: () => {},
});
sub.unsubscribe();

Cleanup patterns:

  • takeUntil(destroy$) in ngOnDestroy
  • async pipe in template
  • take(1) for one-time reads

Continue Learning