scan

function stable

Useful for encapsulating and managing state. Applies an accumulator (or "reducer function") to each value from the source after an initial state is established -- either via a seed value (second argument), or from the first value from the source.

scan<V, A, S>(accumulator: (acc: V | A | S, value: V, index: number) => A, seed?: S): OperatorFunction<V, V | A>

Parameters

accumulator

A "reducer function". This will be called for each value after an initial state is acquired.

seed

Optional. Default is undefined.

The initial state. If this is not provided, the first value from the source will be used as the initial state, and emitted without going through the accumulator. All subsequent values will be processed by the accumulator function. If this is provided, all values will go through the accumulator function.

Returns

OperatorFunction<V, V | A>: A function that returns an Observable of the accumulated values.

Description

It's like reduce, but emits the current accumulation state after each update

scan marble diagram

This operator maintains an internal state and emits it after processing each value as follows:

  1. First value arrives
  • If a seed value was supplied (as the second argument to scan), let state = seed and value = firstValue.
  • If NO seed value was supplied (no second argument), let state = firstValue and go to 3.
  1. Let state = accumulator(state, value).
  • If an error is thrown by accumulator, notify the consumer of an error. The process ends.
  1. Emit state.
  2. Next value arrives, let value = nextValue, go to 2.

Example

An average of previous numbers. This example shows how not providing a seed can prime the stream with the first value from the source.

import { interval, of } from 'rxjs';
import { scan, map } from 'rxjs/operators';

const numbers$ = of(1, 2, 3);

numbers$
  .pipe(
    // Get the sum of the numbers coming in.
    scan((total, n) => total + n),
    // Get the average by dividing the sum by the total number
    // received so var (which is 1 more than the zero-based index).
    map((sum, index) => sum / (index + 1))
  )
  .subscribe(console.log);

Example

The Fibonacci sequence. This example shows how you can use a seed to prime accumulation process. Also... you know... Fibinacci. So important to like, computers and stuff that its whiteboarded in job interviews. Now you can show them the Rx version! (Please don't, haha)

import { interval } from 'rxjs';
import { scan, map, startWith } from 'rxjs/operators';

const firstTwoFibs = [0, 1];
// An endless stream of Fibonnaci numbers.
const fibonnaci$ = interval(1000).pipe(
  // Scan to get the fibonnaci numbers (after 0, 1)
  scan(([a, b]) => [b, a + b], firstTwoFibs),
  // Get the second number in the tuple, it's the one you calculated
  map(([, n]) => n),
  // Start with our first two digits :)
  startWith(...firstTwoFibs)
);

fibonnaci$.subscribe(console.log);

Overloads

scan(accumulator: (acc: V | A, value: V, index: number) => A): OperatorFunction<V, V | A>

Parameters

accumulator

Type: (acc: V | A, value: V, index: number) => A.

Returns

OperatorFunction<V, V | A>

scan(accumulator: (acc: A, value: V, index: number) => A, seed: A): OperatorFunction<V, A>

Parameters

accumulator

Type: (acc: A, value: V, index: number) => A.

seed

Type: A.

Returns

OperatorFunction<V, A>

scan(accumulator: (acc: A | S, value: V, index: number) => A, seed: S): OperatorFunction<V, A>

Parameters

accumulator

Type: (acc: A | S, value: V, index: number) => A.

seed

Type: S.

Returns

OperatorFunction<V, A>

See Also

© 2015–2021 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors.
Code licensed under an Apache-2.0 License. Documentation licensed under CC BY 4.0.
https://rxjs.dev/api/operators/scan