Skip to content

What is RxJS?

Overview

RxJS (Reactive Extensions for JavaScript) is a library for "reactive programming" in JavaScript.

What is reactive programming?

Reactive programming is a method of creating programs that are automatically updated in response to changes in data. It is a type of event-driven programming, with a particular focus on handling asynchronous data streams. It focuses on the flow (stream) of data and builds programs that react to that flow.

In other words, RxJS is a library for handling events and asynchronous data streams in a functional style, providing powerful tools for handling asynchronous data streams using the Observable pattern.

Observable is the core building block of RxJS for representing events and asynchronous data streams. It is a source of values that "flow" and can be received by subscribing. An Observable is a "stream of data" that publishes values over time, and you can receive those values by subscribing to it.

TIP

If you are asking, "What is a stream anyway?" Please refer to What is a Stream?.

Simple Usage Example

ts
import { fromEvent } from 'rxjs';

fromEvent(document, 'click').subscribe(event => {
  console.log('Clicked:', event);
});

Basic Components of RxJS

To master RxJS, it is important to understand the following core components.

ComponentOverview
ObservableThe source of the stream, which represents data that occurs asynchronously or along time.
Observer[1]The entity that subscribes to and receives data from the Observable.
SubscriptionIt manages the subscription and unsubscription of the Observable.
Creation FunctionsA set of functions for creating and combining Observables.
OperatorA set of functions for converting and controlling an Observable.
Subject[2]It is a relay that has the properties of both Observable and Observer.
Scheduler[3]A mechanism to control the timing of Observable execution.

They have their own independent functions, but work together. For example, Creation Functions create and combine Observables, Operators transform and control them, Observers subscribe to them, and Schedulers control execution timing, thus constituting stream processing as a whole.

RxJS Components and Data Flow

※ Detailed usage and examples of each component are explained separately in their own dedicated chapters.

Component Class Diagram

Advantages of RxJS

AdvantageContent
Declarative code[4]Describe "what you want to do" with map, filter, etc. and avoid procedural descriptions such as for loops
Simplify asynchronous processingAvoid nested Promise and callbacks, and write in an intuitive flow
Error handlingUniform handling of errors in streams with .pipe(catchError(...)), etc.
CancelableStream can be suspended by Subscription.unsubscribe()
Various operatorsMany operators such as debounceTime, mergeMap, combineLatest, etc. can be used for conversion and composition

Use Cases

RxJS can be used in any situation where you are dealing with "data that changes over time". Below are some of the key use cases.

Real-time Communication and Streaming

RxJS is especially powerful when dealing with real-time communications such as WebSockets and Server-Sent Events (SSE).

Use CaseDescriptionMain Operators
WebSocket communicationChat, notifications, stock price updates, etc.webSocket, filter, map
Server-Sent EventsPush notifications from serversfromEvent, retry
IoT Sensor MonitoringContinuous sensor data processingdebounceTime, distinctUntilChanged

Simple Example

ts
import { webSocket } from 'rxjs/webSocket';
import { filter } from 'rxjs';

const socket$ = webSocket('wss://example.com/chat');

socket$.pipe(
  filter(msg => msg.type === 'message')
).subscribe(msg => console.log('New message:', msg.text));

UI/State Management & Form Control

Reactive handling of user input and state changes.

Relationship with frameworks

Modern front-end frameworks (Angular Signals, React hooks, Vue Composition API, Svelte Runes, etc.) each provide their own reactive systems. RxJS is a framework-independent library that can be used in conjunction with or separately from these. The integration of RxJS with framework-specific mechanisms will be discussed in detail in Chapter 15, "Framework Integration" (in preparation).

Use CaseDescriptionMain Operators
Input form controlSearch completion, real-time validationdebounceTime, distinctUntilChanged, switchMap
Linking of multiple form itemsUpdate of dependent input itemscombineLatest, withLatestFrom
Inter-component communicationEvent bus and custom state managementSubject, share
UI event processingClick, scroll, drag & dropfromEvent, takeUntil

Simple Example

ts
import { fromEvent, combineLatest } from 'rxjs';
import { debounceTime, map, switchMap } from 'rxjs';

const searchInput = document.querySelector('#search') as HTMLInputElement;
const sortSelect = document.querySelector('#sort') as HTMLInputElement;

const search$ = fromEvent(searchInput, 'input').pipe(
  map(e => (e.target as HTMLInputElement).value)
);

const sort$ = fromEvent(sortSelect, 'change').pipe(
  map(e => (e.target as HTMLSelectElement).value)
);

combineLatest([search$, sort$]).pipe(
  debounceTime(300),
  switchMap(([query, order]) =>
    fetch(`/api/search?q=${query}&sort=${order}`).then(r => r.json())
  )
).subscribe(results => console.log(results));

Offline Support & PWA

Can be used for offline support and network status management in Progressive Web App (PWA).

Use CaseDescriptionMain Operators
Network Condition MonitoringOnline/offline detectionfromEvent, merge
Retry when offlineAutomatic resynchronization when connection is restoredretry, retryWhen
Cache controlService Worker integrationswitchMap, catchError

Simple Example

ts
import { fromEvent, merge } from 'rxjs';
import { map, startWith } from 'rxjs';

const online$ = fromEvent(window, 'online').pipe(map(() => true));
const offline$ = fromEvent(window, 'offline').pipe(map(() => false));

merge(online$, offline$).pipe(
  startWith(navigator.onLine)
).subscribe(isOnline => {
  console.log(isOnline ? 'Online' : 'Offline');
});

AI/Streaming API

This is also ideal for handling streaming API responses such as OpenAI.

Use CaseDescriptionMain Operators
Token sequential outputReal-time display of AI responsesconcatMap, scan
Streaming processingServer-Sent Events processingfromEvent, map
Back-end integrationUse with NestJS (RxJS standard)Various operators

HTTP Communication and Error Handling

Asynchronous HTTP communication can be handled elegantly.

Use CaseDescriptionMain Operators
API RequestsCommunicating with RESTful APIsswitchMap, mergeMap
Error handlingRetries and fallbackscatchError, retry
Timeout controlResponse time limitstimeout
CancellationAborting unnecessary requeststakeUntil, unsubscribe()

State Management & Architecture

It can also be used to design the overall application architecture.

Use CaseDescriptionMain Operators
State Management LibrariesNgRx, Redux-Observable, etc.scan, share
Event flow managementUtilization in DDD (Domain Driven Design)Subject, shareReplay
Data layer separationClean architectureVarious operators

TIP

See also the difference between Promise and RxJS for more information on the use of Promise and RxJS.

Summary

RxJS offers a powerful approach to asynchronous and event-based programming, and its Observable-centric data stream philosophy is particularly useful when dealing with complex asynchronous processing.


  1. The Subscriber class is used as an implementation. For details, see Difference between Observer and Subscriber. ↩︎

  2. A Subject is a special entity that can act as both an Observable that issues values and an Observer that receives values. ↩︎

  3. Scheduler is used to control the execution timing and context of asynchronous processing and is also useful for debugging and performance management. ↩︎

    • Declarative code: straightforward code that says "what kind of result do you want?"
    • Procedural code: code that describes "what kind of calculation should be performed to get the desired result"
    ↩︎

Released under the CC-BY-4.0 license.