Skip to main content

Observables and RxJS Basics

Level: Intermediate

ℹ️ What You'll Learn
  • Observable pattern
  • Creating Observables
  • Subscribing and unsubscribing
  • Common RxJS operators
  • Async pipe
  • Memory leak prevention

Observable Pattern

import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {
subscriber.next('Hello');
subscriber.next('World');
subscriber.complete();
});

observable.subscribe({
next: (value) => console.log(value),
error: (err) => console.error(err),
complete: () => console.log('Done')
});

Observable = stream of values over time.

Subscribe and Unsubscribe

export class StudentListComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];

constructor(private studentService: StudentService) {}

ngOnInit() {
const sub = this.studentService.getStudents()
.subscribe(data => {
this.students = data;
});

this.subscriptions.push(sub);
}

ngOnDestroy() {
// Unsubscribe to prevent memory leaks
this.subscriptions.forEach(sub => sub.unsubscribe());
}
}

Always unsubscribe in ngOnDestroy.

RxJS Operators

import { map, filter, mergeMap } from 'rxjs';

this.studentService.getStudents()
.pipe(
// Transform data
map(students => students.map(s => ({...s, active: true}))),

// Filter
filter(students => students.length > 0),

// Make new request
mergeMap(students => this.getTeachers())
)
.subscribe(data => {
console.log('Processed:', data);
});

Common operators:

  • map = transform
  • filter = filter items
  • mergeMap = chain requests
  • switchMap = cancel prev request
  • tap = side effect (logging)

Async Pipe

<div>{{ students$ | async }}</div>

<tr *ngFor="let student of students$ | async">
<td>{{ student.name }}</td>
</tr>

In component:

students$: Observable<any[]>;

ngOnInit() {
this.students$ = this.studentService.getStudents();
}

Async pipe auto-subscribes/unsubscribes. $ suffix = Observable convention.

Subject (Event Emitter)

import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class StudentService {
private studentSelected = new Subject<any>();
studentSelected$ = this.studentSelected.asObservable();

selectStudent(student: any) {
this.studentSelected.next(student);
}
}

// Component A
selectStudent(student: any) {
this.studentService.selectStudent(student);
}

// Component B
ngOnInit() {
this.studentService.studentSelected$.subscribe(student => {
this.selectedStudent = student;
});
}

Subject = Observable + Observer.

Combining Observables

import { combineLatest, forkJoin } from 'rxjs';

// Wait for all to complete
forkJoin({
students: this.studentService.getStudents(),
teachers: this.teacherService.getTeachers(),
exams: this.examService.getExams()
}).subscribe(({ students, teachers, exams }) => {
console.log('All loaded');
});

// Combine latest values
combineLatest([
this.studentService.getStudents(),
this.route.params
]).subscribe(([students, params]) => {
const filtered = students.filter(s => s.id === params['id']);
});

SMS Example

export class StudentDetailComponent implements OnInit, OnDestroy {
student$: Observable<any>;
private subscriptions = new Subscription();

constructor(
private studentService: StudentService,
private route: ActivatedRoute
) {}

ngOnInit() {
this.student$ = this.route.params.pipe(
switchMap(params => this.studentService.getStudent(params['id']))
);
}

ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}

Template:

<div *ngIf="student$ | async as student">
<h2>{{ student.name }}</h2>
<p>{{ student.email }}</p>
</div>

Key Takeaways

  • Observable = stream of data
  • Subscribe = listen to data
  • Unsubscribe = prevent memory leaks
  • Operators = transform data
  • Async pipe = auto subscribe/unsubscribe
  • Subject = Observable + send events
  • RxJS = powerful reactive programming
💡 Backend Developer Tip

Observables similar to IEnumerable in .NET - lazy evaluation, composition of operations, deferred execution.

⚠️ Observable Issues
  1. Not unsubscribing — Memory leaks
  2. Subscribing multiple times — Multiple calls
  3. Not using async pipe — Manual unsubscribe needed
  4. Wrong operator — Use switchMap not mergeMap for route changes
🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on Observables. Try these prompts:

  • "Why use Observable instead of Promise?"
  • "What's benefit of async pipe?"
  • "When use Subject vs Observable?"
  • "Quiz me on RxJS operators"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

nexcoding.in