Reactgular
Reactgular

Reputation: 54781

Emit previous values as an array in Rxjs 6?

I need an observable that emits an array of previous values upto X number of values.

Basically, something like bufferCount() except that I want it to emit immediately and keep a running history.

of(1,2,3,4,5,6,7,8,9).pipe(
   bufferHistory(3)  // <-- something like this
).subscribe(v => console.log(v));
// starts
// [1]
// [2,1]
// [3,2,1]
// [4,3,2]
// [5,4,3]
// [6,5,4]
// [7,6,5]
// [8,7,6]
// [9,8,7]
// competes

I can't find an operator for Rxjs 6 that does this, and the closest is bufferCount() but it resets after each array is emitted.

The order of the array output doesn't really matter. It can be [3,2,1] or [1,2,3] as that's just semantics right now.

Upvotes: 1

Views: 641

Answers (2)

Naga Sai A
Naga Sai A

Reputation: 10975

To achieve expected result, one option is create Array based on the number using map

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


of(1,2,3,4,5,6,7,8,9).pipe(
   map(x => Array.from(Array(x).keys(), n => n + 1).slice(-3))
).subscribe(v => console.log(v));

working code for reference- https://stackblitz.com/edit/rxjs-gv8ok5?file=index.ts

Upvotes: 0

alexhughesking
alexhughesking

Reputation: 2007

You can use scan for this:

of(1, 2, 3, 4, 5, 6, 7, 8, 9).pipe(
  scan((acc, val) => {
    acc.unshift(val);
    acc.splice(3);
    return acc;
  }, [])
).subscribe(v => console.log(v));

// [1]
// [2,1]
// [3,2,1]
// [4,3,2]
// [5,4,3]
// [6,5,4]
// [7,6,5]
// [8,7,6]
// [9,8,7]

Or:

of(1, 2, 3, 4, 5, 6, 7, 8, 9).pipe(
  scan((acc, val) => {
    acc.push(val);
    return acc.slice(-3);
  }, [])
).subscribe(v => console.log(v));
// [1]
// [1,2]
// [1,2,3]
// [2,3,4]
// [3,4,5]
// [4,5,6]
// [5,6,7]
// [6,7,8]
// [7,8,9]

Upvotes: 3

Related Questions