【问题标题】:RxJS - Infinite scroll - sending requests while previous not arrivedRxJS - 无限滚动 - 在之前未到达时发送请求
【发布时间】:2018-04-24 19:49:18
【问题描述】:

我对响应式编程非常陌生,这是我使用 RxJs 的第一件事,无限滚动:

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);
       });
     });
 }

我的问题是来自测试数据库服务器很远,它需要1+秒才能接收数据。
如果我在没有收到新数据并且页面高度很小的情况下继续滚动,它会继续发送下一页的请求。 我怎样才能让它等待发送请求而没有收到前一个?

【问题讨论】:

    标签: javascript angular typescript rxjs reactive-programming


    【解决方案1】:

    您的订阅过多。编写您的事件流以创建一个 observable。假设 pageByScroll$ 按预期工作,您可以使用 concatMap 将 Observable 流附加在一起(最后一个在下一个开始之前完成,按顺序发出)。

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

    【讨论】:

    • 谢谢您,您的第一部分解决了问题:) 在第二个版本中我遇到了一些问题,但我想这样做。我的代码现在看起来像这样:constructor() { this.newFetchedAdvertisers = this.pageByScroll$.concatMap(t =&gt; this.advertiserService.getAdvertisersByPage(t)); this.advertisers = this.advertisers.concat(this.newFetchedAdvertisers); } advertisers: Observable&lt;AdvertiserClass[]&gt; = this.advertiserService.getAdvertisersByPage(0); 但是新获取的广告商会覆盖实际的广告商,而不是连接两个 observables。
    • 现在在 conturcor 我有这个:this.newFetchedAdvertisers = this.pageByScroll$.concatMap(t =&gt; this.advertiserService.getAdvertisersByPage(t)); this.advertisers = Observable.merge(this.advertisers, this.newFetchedAdvertisers); 并不断覆盖广告商,而不是将新广告“推”给旧广告。我不知道为什么这不起作用:/
    • 如果您将广告客户作为一个数组(而不是作为一个可观察对象),它不起作用吗? Mergemap 会乱序合并,可能不是你想要的
    • 是的,它作为一个数组工作 :) 也尝试了第二种方法,一直保持可观察性,令人沮丧的是我做不到 :)
    • 是的,我想过。第二种方法不起作用,因为每次滚动事件触发时它都会覆盖绑定的 observable 结果。
    【解决方案2】:

    不错的 pageByScroll 功能。

    正如@pixelbits 所说,基本问题是this.pageByScroll$.subscribe() 应该是this.pageByScroll$.map(),但是在玩弄它时我注意到它也在向上滚动页面。

    您可以通过记住上次看到的 scrollTop 来解决这个问题。
    请注意,如果您向下、向上、向下滚动,这也有效。

    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)
    

    【讨论】:

    • 感谢您帮助制作更好的功能:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2017-11-05
    相关资源
    最近更新 更多