There is an Update Below
I am trying to create a buffer of id strings. I want this buffer to close on two predicates:
- times out after a set amount of time that I decide
- it reaches the max buffer size that I decide
Once the buffer closes on either of those two predicates, I want it to pass the array of id strings it collected over to another function. I have code below is the exact setup of how I want to pass data but I am new to RXJS!
class TestClass {
private ids: Array<string>;
private id$: Subject<string> = new Subject();
private buffered$: Observable<Array<string>>;
private timer$: Observable<number>;
constructor() {
this.ids = [];
this.id$ = new Subject<string>();
this.id$.subscribe();
this.timer$ = interval(2000); // timeoutTimer
this.buffered$ = this.id$.pipe(buffer(this.timer$));
this.buffered$.subscribe((idBuffer) => console.log("Id buffer: " + idBuffer));
}
fun1(id: string, x: number) {
this.ids.push(id);
this.id$.next(id); // Source data to be Observed and buffered
return new Promise((reslove) => {
// I want to call fun2 here with
// 1. array from buffer Observable
// 2. the x value from this function
resolve(fun2(buffered, x))
});
}
fun2(ids: Array<string>, x: number) {
console.log('In function 2!');
}
}
let test = new TestClass();
setInterval(() => {
test.fun1('hey' + Math.floor(Math.random() * 10), Math.random());
}, 300);
UPDATE:
I have updated Pseudo Code describing a problem I am facing and how to solve it.
Problem: Essentially I call fun1 multiple times to add things into a buffer, and I want to call fun2 once I have reached a time limit I specify or max buffer size! I then want fun1 to return the corresponding data object that fun2 returns. So I am batching my calls instead of calling fun2 every time I call fun1, I want to wait for the buffer or timeout and return all of the data at once!
I need to find a way to only subscribe the FIRST time fun1 is called and then wait for it's completion to return all the elements, and then once the buffer is empty again subscribe the next FIRST element to be added into the buffer
/*
* PROBLEM: I want this to run only for the first addition of an ID string to a new buffer
* but currently it is returning the new Promise<>... after every call to fun1! This results in
* repeating elements being returned from the Promise
*
* Example:
*
* Buffer = ["id1", "id2", "id3", "id4", "id5"] // We called fun1 five times with these respective IDs
*
* // We are assuming the buffers max out at 3 elements
* (1) idBuffer = ["id1", "id2", "id3"] // After first emission of bufferedIdAccumulator$
* (2) idBuffer = ["id2", "id3", "id4"] // After second emission of bufferedIdAccumulator$
* (3) idBuffer = ["id3", "id4", "id5"] // After third emission of bufferedIdAccumulator$
*
* What I Want:
* (1) idBuffer = ["id1", "id2", "id3"] // After first emission of bufferedIdAccumulator$
* (2) idBuffer = ["id1", "id2", "id3"] // After second emission of bufferedIdAccumulator$
* (3) idBuffer = ["id1", "id2", "id3"] // After third emission of bufferedIdAccumulator$
*
* This is becasuse the first three calls to fun1 contain the first three objects I need to return so I
* only want to return once for all three of these objects
*
*/
fun1(id: string, x: number): Promise<DataClass> {
// console.log("In Function 1!");
this.ids.push(id);
this.id$.next(id); // Source data to be Observed and buffered
console.log(`Adding id: ${id} to buffer!`);
return new Promise<DataClass>(async (resolve) => {
// I want to call fun2 here with
// 1. array from buffer Observable
// 2. the x value from this function
let idBuffer = await firstValueFrom(this.bufferedIdAccumulator$);
// let idBuffer = await new Promise<Array<string>>((resolve) => {
// this.bufferedIdAccumulator$.subscribe((idBuffer) => {
// console.log(idBuffer);
// resolve(idBuffer);
// });
// });
console.log(`<fun1> idBuffer: ${idBuffer}`);
let dataClasses = this.fun2(idBuffer, x);
let dataClass = dataClasses[0];
resolve(dataClass);
});
}
fun2(ids: Array<string>, x: number): Array<DataClass> {
// console.log('In function 2!');
// console.log('\nFunction 2:');
// console.log(ids);
let dataClasses = [];
ids.forEach((id) => {
dataClasses.push(new DataClass(id, x));
});
return dataClasses;
}
}
class DataClass {
id: string;
x: number;
constructor(id: string, x: number) {
this.id = id;
this.x = x;
}
}
let test = new TestClass();
let x = 0;
setInterval(() => {
test.fun1('hey' + x++, Math.random()); // Math.floor(Math.random() * 10), Math.random()
}, 2500);