user8778731
user8778731

Reputation: 155

RxJS - Infinite scroll - sending requests while previous not arrived

I'm very new to reactive programming, this is my first thing with RxJs, an infinite scrolling:

public pageByScroll$ = Observable.fromEvent(window, "scroll")
  .map(() => document.documentElement.scrollHeight - document.documentElement.scrollTop - document.documentElement.clientHeight)
  .filter(x => x < 800)
  .debounceTime(200)
  .scan(count => count + 1, 0);


handleScroll() {
  this.pageByScroll$.subscribe(
    pageToLoad => this.advertiserService
      .getAdvertisersByPage(pageToLoad)
      .subscribe(advertisers => this.advertisers = this.advertisers.concat(advertisers))
  );
};

getAdvertisersByPage(page: number): Observable<AdvertiserClass[]> {
    return this.http.get(this.advertisersUrl + '/pager/' + page)
     .map(res => {
       return res.json().map(advertiser => {
         return new AdvertiserClass(advertiser);
       });
     });
 }

My problem is comes from test db server is far away, and its need 1+sec to receive the data.
If i keep scrolling while the new data is not received and the pages height is small, it keeps sending request for the next page. How could i make it to wait sending requests while the previous is not received?

Upvotes: 1

Views: 896

Answers (2)

Michael Kang
Michael Kang

Reputation: 52867

You have too many subscribes. Compose your event streams to create one observable. Assuming, pageByScroll$ works as intended, you can use concatMap to append Observable streams together (last one completes before next one begins, emitted in order).

var o= this.pageByScroll$.concatMap(t=>this.getAdvertisersByPage(t));
o.subscribe(t=> this.advertisers.concat(t));

Upvotes: 1

Richard Matsen
Richard Matsen

Reputation: 23483

Nice pageByScroll function.

As @pixelbits says, the basic problem is this.pageByScroll$.subscribe() should be this.pageByScroll$.map(), but playing around with it I notice it also pages on scroll-up.

You might solve that by remembering the scrollTop last seen.
Note this also works if you scroll down, up, down.

const pageByScroll$ = Observable.fromEvent(window, "scroll")
  .map(() => document.documentElement.scrollTop)
  .scan((scrollTop, last) => scrollTop > last ? scrollTop : last, 0)
  .distinctUntilChanged()
  .map(downwardScrollTop => 
    document.documentElement.scrollHeight
       - downwardScrollTop
       - document.documentElement.clientHeight
    )
  .filter(x => x < 800)
  .debounceTime(200)
  .scan(count => count + 1, 0)

Upvotes: 2

Related Questions