#rxjs
#tutorial
#intermediate
Day 6: Transformation Operators (scan, reduce)
Day 6: Accumulating Data
How do we maintain state in a stream? Like “Total Price” or “Current Score”? We use accumulation operators.
1. scan
The RxJS equivalent of Array.reduce, but it emits every intermediate result. Ideally suited for managing state over time (like a Redux store).
import { of } from 'rxjs';
import { scan } from 'rxjs/operators';
const numbers$ = of(1, 2, 3);
numbers$.pipe(
// (accumulator, current) => newAccumulator
scan((total, n) => total + n, 0) // Start with 0
).subscribe(console.log);
// Output:
// 1 (0 + 1)
// 3 (1 + 2)
// 6 (3 + 3)
Real World: Tracking a click count.
fromEvent(document, 'click').pipe(
map(() => 1),
scan((acc, curr) => acc + curr, 0)
).subscribe(count => console.log('Click count:', count));
2. reduce
Works exactly like scan, but waits for the Observable to complete and emits only the final result.
import { of } from 'rxjs';
import { reduce } from 'rxjs/operators';
of(1, 2, 3).pipe(
reduce((total, n) => total + n, 0)
).subscribe(console.log);
// Output:
// 6
Note: reduce emits nothing if the source never completes (like an interval or click listener).
3. mapTo (Deprecated but common)
Often replaced by map(() => value). It simply maps every emission to a constant.
Homework for Day 6:
- Create an interval that emits every 100ms.
- Use
scanto accumulate the values into an array. - Use
take(5)to stop it. - Output should look like:
[0],[0, 1],[0, 1, 2]…
Get ready. Day 7 is the big one. Flattening Maps (switchMap, mergeMap).