I'm trying to implement the show more button functionality, when you press it should call the api with the next offset and merge the value with the previous result. From what I saw so far I should use the SCAN function, however I'm lost.
When I click show more the offset is updated
public showMore(offset:number){
this.offset$.next(offset)
}
The api is returning this object
{
requestInfo:Info,
product:Product[]
}
Info contains the number of results and the next offset, product contains a list of product (product name, price etc...)
What I tried so far is
public getProductsV3():Observable<ProductResponseApi>{
const combineLatest$ = combineLatest([this.offset$,this.limit$]).pipe(
switchMap(([offset,limit])=>this.fetchProductsFromApiV2(offset,limit))
)
return combineLatest$.pipe(
scan((prev,current)=> {infos:current.infos,products:[...prev.product,...current.products]} )
)
}
But obviously it doesn't work
public getProductsV2():Observable<ProductResponseApi>{
return combineLatest$ = combineLatest([this.offset$,this.limit$]).pipe(
switchMap(([offset,limit])=>this.fetchProductsFromApiV2(offset,limit))
)
}
The version 2 is working, however it shows the next pages without keeping the old values.
The fetchProduct is quite simple
private fetchProductsFromApiV2(currentOffset:number,limit:number){
const params = new HttpParams().set('offset', currentOffset).set('limit', limit);
return this.http.get<ProductResponseApi>(this.apiUrl '/products',{params,withCredentials:true});
}
Thanks for help
CodePudding user response:
It looks like you're on the right track with using the scan() operator. The scan() operator is used to combine the elements of an observable sequence into a single value. It works by applying a function to each element of the sequence, and then carrying over the result of the function to the next element.
In your case, you want to use scan() to combine the previous result with the current result to build up a list of products. To do this, you can use the following code:
public getProductsV3(): Observable<ProductResponseApi> {
const combineLatest$ = combineLatest([this.offset$, this.limit$]).pipe(
switchMap(([offset, limit]) => this.fetchProductsFromApiV2(offset, limit))
);
return combineLatest$.pipe(
scan((prev, current) => {
return {
infos: current.infos,
products: [...prev.products, ...current.products]
};
})
);
}
In the scan() operator, the first argument is the previous value, and the second argument is the current value. In this case, the previous value is an object with an infos property and a products property, and the current value is also an object with the same structure. The scan() operator is applied to each emitted value, and the result of the function is carried over to the next value.
In the function passed to scan(), we create a new object with the infos property set to the infos property of the current value, and the products property set to the concatenation of the previous products array and the current products array. This will build up a list of products over time as the values are emitted by the observable.