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
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.
| Component | Overview |
|---|---|
Observable | The 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. |
Subscription | It manages the subscription and unsubscription of the Observable. |
Creation Functions | A set of functions for creating and combining Observables. |
Operator | A 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
| Advantage | Content |
|---|---|
| Declarative code[4] | Describe "what you want to do" with map, filter, etc. and avoid procedural descriptions such as for loops |
| Simplify asynchronous processing | Avoid nested Promise and callbacks, and write in an intuitive flow |
| Error handling | Uniform handling of errors in streams with .pipe(catchError(...)), etc. |
| Cancelable | Stream can be suspended by Subscription.unsubscribe() |
| Various operators | Many 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 Case | Description | Main Operators |
|---|---|---|
| WebSocket communication | Chat, notifications, stock price updates, etc. | webSocket, filter, map |
| Server-Sent Events | Push notifications from servers | fromEvent, retry |
| IoT Sensor Monitoring | Continuous sensor data processing | debounceTime, distinctUntilChanged |
Simple Example
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 Case | Description | Main Operators |
|---|---|---|
| Input form control | Search completion, real-time validation | debounceTime, distinctUntilChanged, switchMap |
| Linking of multiple form items | Update of dependent input items | combineLatest, withLatestFrom |
| Inter-component communication | Event bus and custom state management | Subject, share |
| UI event processing | Click, scroll, drag & drop | fromEvent, takeUntil |
Simple Example
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 Case | Description | Main Operators |
|---|---|---|
| Network Condition Monitoring | Online/offline detection | fromEvent, merge |
| Retry when offline | Automatic resynchronization when connection is restored | retry, retryWhen |
| Cache control | Service Worker integration | switchMap, catchError |
Simple Example
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 Case | Description | Main Operators |
|---|---|---|
| Token sequential output | Real-time display of AI responses | concatMap, scan |
| Streaming processing | Server-Sent Events processing | fromEvent, map |
| Back-end integration | Use with NestJS (RxJS standard) | Various operators |
HTTP Communication and Error Handling
Asynchronous HTTP communication can be handled elegantly.
| Use Case | Description | Main Operators |
|---|---|---|
| API Requests | Communicating with RESTful APIs | switchMap, mergeMap |
| Error handling | Retries and fallbacks | catchError, retry |
| Timeout control | Response time limits | timeout |
| Cancellation | Aborting unnecessary requests | takeUntil, unsubscribe() |
State Management & Architecture
It can also be used to design the overall application architecture.
| Use Case | Description | Main Operators |
|---|---|---|
| State Management Libraries | NgRx, Redux-Observable, etc. | scan, share |
| Event flow management | Utilization in DDD (Domain Driven Design) | Subject, shareReplay |
| Data layer separation | Clean architecture | Various 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.
The Subscriber class is used as an implementation. For details, see Difference between Observer and Subscriber. ↩︎
A Subject is a special entity that can act as both an Observable that issues values and an Observer that receives values. ↩︎
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"