1
  • There is a function that would get called from anywhere within the application, which would be passed an object.
  • What we need to do, is call a backend API with this item as Post
    Body.
  • However, what I would like to do is collate these updates for an interval of time - and then send them across together, to
    reduce the number of calls made to backend.

So, I am thinking of adding these items to an Array . Create an observable with this array and pipe bufferTime to buffer the values for a specific amount of time, before emitting them.

I created a Stackblitz - https://stackblitz.com/edit/typescript-fzezep?file=index.ts&devtoolsheight=100 and if you see the output - The first 20 values are output, the ones that are added before subscribing. But the last 20 values are never emitted.

So the subscription is complete, but then how do we create a subscription with a dynamic array?

Roshan Khandelwal
  • 953
  • 1
  • 11
  • 17

1 Answers1

4

That a pretty common rxjs mistake that you have done there.

So first lets go trouh your exmaple line by line

// You create an empty array
const dataArray = [];

// You create an observable that will point to the created dataArray
const bufferBy = from(dataArray);
let myBufferedInterval;

// You fill the dataArray with 20 elements
for (var i = 0; i <= 20; i++) {
  dataArray.push(i);
}
// You create an observable that has will have for it's source from(dataArray)
myBufferedInterval = bufferBy.pipe(bufferCount(5));
// You create a SUBSCRIPTION on myBufferInterval which will go upstream to the observable that points to the dataArray with 20 element and make everything alive
const buffered = myBufferedInterval.subscribe(val => console.log(val));

// Here you add more element to the dataArray, but they will not result with new values in your subscription as your subscription points to the instance of dataArray with 20 elements (so each subscribe makes a individual subscription pointing to it's own instance of the dataArray)
for (var i = 21; i < 40; i++) {
  dataArray.push(i);
}

console.log(dataArray)

// If you create new subscriton here it will have as reference an array that holds 40 elements. so you will be able to see the rest of the numbers (20+)

myBufferedInterval.subscribe(val => console.log(val));

The rxjs way of handling this will be something like the following snippet. The difference is that instead of using an array im using the rxjs Subject object that supports the method next.

So the thing that I'am doing is to create a subscriton to this Subject, pipe it down trough a buffer, in order to have batches of 5 elemnts and I start waiting for the buffer to get filled.

After that whenever i use the next method the Subject will emit a new value to it's subscribers and in our case it will start filling our buffer.

let { from, interval, Subject } = rxjs;
let { bufferCount, bufferTime } = rxjs.operators;

const requestHolder = new Subject();
requestHolder.pipe(bufferCount(5)).subscribe(val => console.log(val));

for (var i = 0; i <= 10; i++) {
  requestHolder.next(i);
}

for (var i = 11; i < 20; i++) {
  requestHolder.next(i);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.3/rxjs.umd.min.js"></script>