Reputation: 101
I do an HTTP request to an API that returns 350 records. Each item have a property called "total". I need to select 5 items randomly but also, the sum of the property "total" of those 5 items should be less than 30. I think this can be done using takeUntil, but I still don't know how to build the code in order to accomplish that.
products$ = combineLatest([
this._productService.robots$,
this.refreshProductAction$
]).pipe(
map(([products, action]) =>
products.sort(() => (Math.random() - Math.random())).slice(0, 5),
)
);
The is one example of "expand" operator, but i don't know how to keep track of the sum and the re execute the observable again in case is higher than 50.
Upvotes: 0
Views: 621
Reputation: 17752
If I understand right, you receive 350 "products" with just one API invocation which needs to be repeated if the sum of "total" of 5 randomly chosen "products" is higher than 50.
So, if this understanding is correct, I would proceed using expand
operator to recursively invoke the API until the desired condition is met and then use the last
operator to notify only the last value emitted, which is the first one satisfying the condition. The following example tries to explain the logic with inline comments.
products$ = combineLatest([
this._productService.robots$,
this.refreshProductAction$
]).pipe(
// use expand operator to recursively repeat the API call if the sum is higher than 50,
// otherwise return the empty Observable, which means simply to complete the stream
expand(([products, action]) => {
const fiveProducts = products.sort(() => (Math.random() - Math.random())).slice(0, 5);
// use the "reduce" method of Array to calculate the sum
const sumOfFiveTotals = fiveProducts.reduce((s, p) => s = s + p.total, 0);
return sumOfFiveTotals > 50 ?
// I assume this._productService.robots$, when subscribed, calls the API
// you can pipe a "delay" operator after this._productService.robots$ if you want to add some delay between subsequent API calls
this._productService.robots$ :
EMPTY // the empty Observable
}),
// notifies only the last value emitted by the upstream
last()
);
Upvotes: 1