Reputation: 3071
Requirement: call an observable on remote server to get list of product ids. Call Firebase to get product detail (for each product id).
The following code works but it feels more like a promise implementation than an observable implementation. Note that code samples are simplified and somewhat pseudo code.
In theory, this could be solved by calling one Firebase observable that returns all products e.g. where productid in (35, 68). But I can't find a way to do this in Firebase. Instead I make one call for each product id.
this.predicitionioService.getProductIds()
.subscribe(
ids => {
this.productService.getProduct(ids[0].id).subscribe(product => this.product1 = product);
this.productService.getProduct(ids[1].id).subscribe(product => this.product2 = product);
}
);
flatMap is ballpark what's needed here. But the data returned is for the last product only.
this.predicitionioService.getProductIds()
.flatMap((ids) => this.productService.getProduct(ids[0].id))
.flatMap((ids) => this.productService.getProduct(ids[1].id))
.subscribe(
merge kind of gets me there but also returns product ids in the subscribe next function. And I need products to have an index e.g. product 1, 2, 3. I can't just bind a single list. This seems to work with assigning my own index e.g. i++. But again this gets messy.
this.predicitionioService.getProductIds()
.merge(
this.productService.getProduct(ids[1].id),
this.productService.getProduct(ids[2].id)
)
.subscribe(
Is there a better way of implementing this with observable methods?
Upvotes: 1
Views: 717
Reputation: 1470
var maxConcurrent = 5;
this.predicitionioService.getProductIds() // => Observable of array of ids, 1 item
.mergeMap(ids => Observable.from(ids)) // => Observable of ids
.mergeMap(id => this.productService.getProduct(id.id), null, maxConcurrent) // => Observable of products
.subscribe(product => { /* do stuff */ }); // do stuff to each product
Notes:
.subscribe
with .toArray()
maxConcurrent
parameter is the maximum number of concurrent requests to getProduct
. If you need to preserve the order of products (same order as in the original ids
array), set this to 1 - but it will be slower. (mergeMap
with maxConcurrent
= 1 would be equivalent to concatMap
)
Upvotes: 3
Reputation: 5730
This should do what you need:
this.predicitionioService.getProductIds()
.flatMap((ids) => {
return Observable.forkJoin(
ids.map(
(id) => this.productService.getProduct(id.id)
)
);
})
.subscribe((products) => {
//do stuff
});
This will return an array with all results of the getProduct()
;
Upvotes: 1