Lessons43. scan: state as accumulation
Lessons · 43
43. scan: state as accumulation
scan — reduce over time
If you know Array.prototype.reduce, scan works almost the same way, but with one important difference: it emits the intermediate result after every value, not just the final one.
from([1, 1, -1, 1]).pipe(scan((acc, x) => acc + x, 0))
// 0+1=1 → next(1)
// 1+1=2 → next(2)
// 2-1=1 → next(1)
// 1+1=2 → next(2)
Why this is so powerful
UI state is often born from a sequence of events: a "plus" click → +1, a "minus" click → −1, adding a todo → a new item in the list. scan turns a stream of events into a stream of states.
The signature
scan(reducer, seed):
reducer(acc, value) => newAcc— a function that takes the accumulator and a value and returns the new accumulator.seed— the accumulator's starting value.
Your task
- In
pipe, addscan((count, change) => count + change, 0). - Expected output:
Count: 1 → Count: 2 → Count: 1 → Count: 2.
Solution spoiler · click to reveal
const { from, scan } = Rx;
const changes$ = from([1, 1, -1, 1]);
const count$ = changes$.pipe(
scan((count, change) => count + change, 0)
);
count$.subscribe(value => console.log('Count: ' + value)); script.ts
CONSOLE · Console output
Hit Run to see the result...