RxJS reduces ReplaySubject

I am using ReactiveX / RxJS version.

Let's say that I have an Rx.ReplaySubject that every 2 seconds emits an object containing an identifier and an array with values. I want to reduce this array of values ​​and get their sum.

The problem is that the ReplaySubject is hot observable and never completes, at least I don't want it to end because I want the sum of these object values ​​every 2 seconds. But in order to use the reduction operator, the observable must be completed. So how should I proceed?

Invalid EG code:

var subject = new Rx.ReplaySubject();

subject.
  map(x => x.transactions).
  // Reduce never concludes because ReplaySubject instance is not completed
  reduce((v1, v2) => v1+v2, 0).
  subscribe(function (value) {
    console.log(value)
  });

setInterval(injectData, 2000);

function injectData () {
  subject.next({id: Date.now(), transactions: [
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)}
  ]});
}
+4
source share
1 answer

Observable.prototype.scan() ( RxJS)

scan() , reduce(), . (. Rx scan reduce)

OP ( fiddle):

var subject = new Rx.ReplaySubject();

subject
  // note: use "selectMany" to flatten observable of observables
  .selectMany(x => Rx.Observable.fromArray(x.transactions))
  // note: use "scan" to aggregate values
  .scan((agg, val) => agg+val.value, 0)
  .subscribe(function (value) {
    console.log(value)
  });

setInterval(injectData, 2000);

function injectData () {
  subject.onNext({id: Date.now(), transactions: [
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)},
    {value: Math.round(Math.random() * 5000)}
  ]});
}

:

- selectMany(). , 2 , , reduce() ( fiddle)

subject
  // note: use "selectMany" to flatten observable of observables
  // note: using "reduce" inside here so that we only emit the aggregate
  .selectMany(x => 
    Rx.Observable
      .fromArray(x.transactions)
      .reduce((agg, val) => agg + val.value, 0)
  )
  // note: use "scan" to aggregate values
  .scan((agg, val) => agg+val, 0)
  .subscribe(function (value) {
    console.log(value)
  });

:

Rx ; onCompleted(), . , reduce(). fiddle .

+5

All Articles