RxJS (Reactive Extensions for JavaScript) uses Observables to handle asynchronous data streams, and operators help you manipulate these streams. Operators are usually divided into creation, transformation, filtering, combination, and utility operators. Here’s a detailed overview:
1. Creation Operators
These operators are used to create Observables.
of
Emits a sequence of values you provide.
import { of } from 'rxjs';
of(1, 2, 3).subscribe(value => console.log(value));
// Output:
// 1
// 2
// 3
from
Converts an array, promise, or iterable into an Observable.
import { from } from 'rxjs';
from([10, 20, 30]).subscribe(value => console.log(value));
// Output:
// 10
// 20
// 30
2. Transformation Operators
Used to transform items emitted by an Observable.
map
Transforms each emitted value.
import { of } from 'rxjs';
import { map } from 'rxjs/operators';
of(1, 2, 3)
.pipe(map(x => x * 10))
.subscribe(value => console.log(value));
// Output:
// 10
// 20
// 30
switchMap
Maps to an inner Observable, switching to the new one whenever a new value is emitted.
import { of, interval } from 'rxjs';
import { switchMap, take } from 'rxjs/operators';
of('A', 'B')
.pipe(
switchMap(val => interval(1000).pipe(take(3)))
)
.subscribe(console.log);
// Output: (each letter triggers a new interval)
// 0,1,2 for 'A'
// 0,1,2 for 'B' (switches to new Observable)
3. Filtering Operators
Filter values emitted by an Observable.
filter
Emit only values that pass a condition.
import { of } from 'rxjs';
import { filter } from 'rxjs/operators';
of(1, 2, 3, 4)
.pipe(filter(x => x % 2 === 0))
.subscribe(console.log);
// Output:
// 2
// 4
take
Emit only the first N values.
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
interval(1000)
.pipe(take(3))
.subscribe(console.log);
// Output:
// 0
// 1
// 2
4. Combination Operators
Combine multiple Observables.
merge
Combine multiple Observables concurrently.
import { merge, interval } from 'rxjs';
import { take } from 'rxjs/operators';
const obs1 = interval(1000).pipe(take(3));
const obs2 = interval(500).pipe(take(3));
merge(obs1, obs2).subscribe(console.log);
// Output: interleaved values from both observables
concat
Emit values from one Observable, then the next.
import { concat, of } from 'rxjs';
const obs1 = of(1, 2);
const obs2 = of(3, 4);
concat(obs1, obs2).subscribe(console.log);
// Output:
// 1
// 2
// 3
// 4
5. Utility Operators
Operators for side effects or additional behaviors.
tap
Perform a side effect without changing values.
import { of } from 'rxjs';
import { tap, map } from 'rxjs/operators';
of(1, 2, 3)
.pipe(
tap(x => console.log('Before map:', x)),
map(x => x * 2),
tap(x => console.log('After map:', x))
)
.subscribe();
// Output:
// Before map: 1
// After map: 2
// Before map: 2
// After map: 4
// Before map: 3
// After map: 6
debounceTime
Delay emissions until a certain time has passed without new events (useful for search inputs).
import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';
const input = document.getElementById('search');
fromEvent(input, 'keyup')
.pipe(
debounceTime(500),
map(event => event.target.value)
)
.subscribe(value => console.log(value));
This is just the tip of the RxJS iceberg, but these operators are among the most commonly used. With these, you can handle most async flows in a reactive style.