Home > Enterprise >  What RxJS operation should I use in getting data from an observable and pushing it to an array?
What RxJS operation should I use in getting data from an observable and pushing it to an array?

Time:05-18

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!

CodePudding user response:

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.

CodePudding user response:

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>
  • Related