'What RxJS operation should I use in getting data from an observable and pushing it to an array?
I'm trying to simulate an http request that supports pagination. For now, this request only returns a number. A parameter of the get request is the page number used in the database.
To be simpler, consider the function getData that returns an observable that returns the page number.
getData(page:number):Observable<number>{
return new Observable<number>(observer => {
observer.next(page)
})
}
Inside my ngOnInit, I declared:
data$!:Observer<number>
page:number = 0
ngOnInit():void{
this.data$ = this.getData(page).pipe(
//RxJS opeartor so that the data:number received will be converted to an array
)
}
I am also trying to code declaratively/reactively by avoiding subscribe() method. So my approach in the template is something like
<div *ngFor="let data of data$ | async"> {{data}} </div>
Lastly, to simulate the "load more" feature, I added <button (click)="loadMore()">Load More</button> in the template. And in the component,
loadMore():void{
this.data$ = this.getData(++this.page).pipe(
//I want to know what should be the RxJS operator that I should use here so that the data<number> that is emitted from the observable, will be appended to this.data$.
)
}
So if I clicked the Load More button 3 times, my template should display
0
1
2
I am open for other approaches as long as it does not use subscribe(). Thank you!
Solution 1:[1]
Angular has a subscribe method to work with Observable. I think the easiest way is to use subscribe. Here's an example:
data: any;
loadMore(): void {
this.getData(++this.page)
.subscribe(d => {
this.data = d;
});
}
Look all the changes that I did first. Check the data variable is now type any, because I don't know what is your data response type. Let me know if it works for you.
Solution 2:[2]
In rxjs the standard operator to convert observable data is map.
usage is simple, and similar to Array.map:
loadMore():void{
this.data$ = this.getData(++this.page).pipe(
map(dataIn => ({ dataIn, page: this.page }))
)
}
As you pointed out, it is not good practice to subscribe to observables from the component (it might lead you into the memory-leak trap).
Instead of subscribing you should return an observable (or set a variable with the observable as you did) and use the async pipe from the views to extract its values (it subscribes/uinsubscrives as necessary, which voids the issues):
<div>{{ (data$ | async)?.page }}</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jose Vicente |
| Solution 2 | The Fabio |
