Reactive Programming
Modelling asynchronous data streams and propagating change automatically.
Overview
Reactive Programming models asynchronous data as streams of events over time. Observers subscribe to Observables and react to emitted values, errors, and completion signals. The Reactive Manifesto (2013) describes reactive systems as responsive, resilient, elastic, and message-driven. RxJS, RxJava, and Reactor are the dominant implementations.
Origin
Microsoft Research introduced Reactive Extensions (Rx) for .NET in 2009, designed by Erik Meijer. It was subsequently ported to JavaScript (RxJS, 2011), Java (RxJava, Netflix, 2013), and other platforms. The Observer pattern (GoF, 1994) is a precursor; Rx adds composable operators and backpressure handling.
Examples
Debounced search with RxJS
import { fromEvent, switchMap, debounceTime, distinctUntilChanged, map } from 'rxjs';
import { ajax } from 'rxjs/ajax';
const searchInput = document.getElementById('search') as HTMLInputElement;
const search$ = fromEvent(searchInput, 'input').pipe(
map(e => (e.target as HTMLInputElement).value.trim()),
debounceTime(300),
distinctUntilChanged(),
switchMap(query =>
query.length >= 2
? ajax.getJSON<{ results: string[] }>('/api/search?q=' + query)
: []
)
);
search$.subscribe({
next: data => renderResults(data.results),
error: err => console.error('Search failed:', err),
});switchMap cancels the previous in-flight request when a new keystroke arrives. debounceTime(300) waits 300ms after the last event. distinctUntilChanged prevents redundant requests for identical queries.
WebSocket stream with error recovery in RxJS
import { webSocket } from 'rxjs/webSocket';
import { retryWhen, delay, tap } from 'rxjs/operators';
interface TradeEvent {
symbol: string;
price: number;
volume: number;
}
const socket$ = webSocket<TradeEvent>('wss://exchange.example.com/trades');
socket$.pipe(
retryWhen(errors =>
errors.pipe(
tap(err => console.warn('WS disconnected, retrying...', err)),
delay(3000)
)
)
).subscribe(trade => {
console.log(trade.symbol, trade.price, trade.volume);
});retryWhen provides fine-grained reconnection logic. delay(3000) prevents tight reconnect loops. In RxJS 7+ prefer retry({ delay: 3000, resetOnSuccess: true }) over retryWhen which is deprecated.
Use Cases
- 01Real-time dashboards (stock tickers, live metrics) where values change continuously and the UI must reflect current state
- 02Autocomplete and typeahead components where keystroke events must be debounced, deduplicated, and mapped to async HTTP calls
- 03Event-driven microservices using Kafka or RabbitMQ where each service processes a stream of domain events
- 04UI state coordination across multiple async sources (WebSocket, polling, user input) that need to be merged and transformed uniformly
When Not to Use
- //Simple one-off HTTP requests; wrapping fetch in an Observable adds ceremony without compositional benefit
- //Teams without RxJS experience; the operator catalogue (100+ operators) and marble diagrams have a documented high learning curve
- //Synchronous algorithms where a plain loop is clearer; reactive abstractions are built for async time-based coordination, not for transforming arrays in memory
Technical Notes
- Hot observables (subjects, fromEvent) emit regardless of subscribers; cold observables (ajax, timer) begin executing per-subscriber. Misunderstanding this distinction causes resource leaks and duplicated HTTP calls
- Backpressure in reactive systems describes the condition where producers emit faster than consumers process; RxJava 2 introduced Flowable (with backpressure) distinct from Observable (without); RxJS handles this via operators like throttleTime and bufferTime
- switchMap, mergeMap, concatMap, and exhaustMap differ in how they handle overlapping inner observables: cancel, merge, queue, and ignore respectively. switchMap is correct for HTTP search; concatMap is correct for sequential writes
- The TC39 Observable proposal has been at Stage 1 since 2015; built-in browser Observables are not imminent. RxJS 7 is the de-facto standard for browser and Node.js reactive code as of 2024
More in Types of Programming