BACK
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

  1. In pipe, add scan((count, change) => count + change, 0).
  2. 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 // TypeScript
CONSOLE · Console output
Hit Run to see the result...