How to get data in chunks from an API using rxjs interval and stop when there is no data left

1k Views Asked by At

I am trying to load data in chunks on timely basis. for this I am using thee methods.

This function loads data from a json object that I am using to mimic api data

 getScrollingData(startIndex, endIndex){
    if(this.items.data.length>endIndex){
      return of(this.items.data.slice(startIndex, endIndex));
    }else{
      return of(null)
    }
  }

The getData method below is being used to send request every two seconds

getData(){
const secondsCounter = interval(2000); 
return secondsCounter
.pipe(
  flatMap((res) => {
    if(res!=null)
     return this.mimicApiService.getScrollingData(res, res+10)
            .takeUntil(v => v != null)// this causes error
  }),
  
  
)

}

In the ngOnInit of component I am subscribing to getData to load that data into array to be displayed on the screen

data = [];
ngOnInit() {
  this.dataService.getData().subscribe((res)=>{
    this.data = [...this.data, ...res];
  });
}

Questions

  1. I am getting error Argument of type '(v: any) => boolean' is not assignable to parameter of type 'Observable<any>' from takeUntil. Can you please tell why this happens?
1

There are 1 best solutions below

1
Moshezauros On

You are using the wrong operator, takeUntil wants an observable and will stop taking once that observable emits.

What you need is takeWhile, which suits your use case better:

takeWhile(v => v != null)

and here is the doc

Edit: if you also want to stop the interval when there is no more data returned from getScrollingData, you can do something like the following:

getData() {
  const stopInterval = new Subject();
  const secondsCounter = interval(2000)
    .pipe(takeUntil(stopInterval));
  return secondsCounter
    .pipe(
      flatMap((res) => {
        if (res != null)
          return this.getScrollingData(res, res + 2)
      }),
      takeWhile(v => {
        if (v == null) {
          stopInterval.next();
          return false;
        }
        return true;
      }))
}

once we emit from stopInterval, takeUntil of interval will trigger.