No history yet

Introduction to RxJS

The Stream of Data

RxJS is a library for composing asynchronous and event-based programs by using observable sequences. Think of it as a toolkit for handling data that arrives over time, like user clicks, keyboard inputs, or information from an API.

Imagine a conveyor belt at a factory. Items (data) appear on the belt at different times. RxJS lets you set up workstations along this belt to inspect, modify, or combine these items as they pass by. This conveyor belt is called an Observable.

The Core Components

RxJS has three key parts that work together: the Observable, the Observer, and the Subscription. They form a push-based system. Instead of asking for data, the Observable pushes data to the Observer whenever it's available.

An Observable is like a newsletter producer. An Observer is the subscriber who reads it. A Subscription is the connection between them, representing the ongoing delivery.

An Observable is a source of data. It can emit multiple values over time, a single value, or no values at all. It doesn't do anything until someone subscribes to it. This makes it lazy—no work is performed until it's needed.

Here’s how you can create a simple Observable that emits the numbers 1, 2, and 3 in sequence and then completes.

import { Observable } from 'rxjs';

const myObservable = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  subscriber.complete();
});

An Observer is an object with a set of callbacks that listen for values delivered by the Observable. It has three main methods:

  • next(): Called whenever the Observable emits a new value.
  • error(): Called if the Observable encounters an error. The stream stops after this.
  • complete(): Called when the Observable has no more values to emit. The stream is finished.
const myObserver = {
  next: value => console.log('Value received:', value),
  error: err => console.error('Error occurred:', err),
  complete: () => console.log('Stream complete!')
};

Finally, a Subscription connects an Observer to an Observable. When you call the .subscribe() method on an Observable, you create this connection, and the Observable starts emitting values. The subscribe() method returns a Subscription object, which has an important unsubscribe() method. Calling this tears down the subscription, stopping the flow of data and freeing up memory.

// This line activates the observable
const subscription = myObservable.subscribe(myObserver);

// To stop receiving values
subscription.unsubscribe();

The Power of Operators

Observables on their own are simple. Their true power comes from operators. Operators are pure functions that let you transform, filter, combine, and manipulate the stream of data from an Observable in various ways.

Think of the conveyor belt again. Operators are like robotic arms placed along the belt. One might pick up only the red items (filter), another might paint each item blue (map), and a third might delay an item for a few seconds (delay). Each operator takes an Observable as input and produces a new, modified Observable as output.

You can chain operators together using the .pipe() method. This creates a clean, readable pipeline for your data to flow through.

import { of } from 'rxjs';
import { map, filter } from 'rxjs/operators';

const source = of(1, 2, 3, 4, 5);

const example = source.pipe(
  // Only let even numbers pass through
  filter(num => num % 2 === 0),
  // Multiply each even number by 10
  map(num => num * 10)
);

// Output will be: 20, 40
example.subscribe(value => console.log(value));

Operators allow you to build complex asynchronous logic in a declarative way, making your code easier to read and manage.

With these fundamentals, you have the building blocks to handle complex data flows. The Observable provides the stream, the Observer consumes it, and Operators give you precise control over what happens in between.