如何将rrjjs中的Scheduler.animationFrame和fromEvent(window,'scroll')流结合起来?

如何将rrjjs中的Scheduler.animationFrame和fromEvent(window,'scroll')流结合起来?

问题描述:

我有两个观察对象Observable.of(0, animationFrame) & Observable.fromEvent(window, 'scroll')。我想合并它们,这样我的renderScrollBar(event)只在animationFrame的tick上被调用。如何将rrjjs中的Scheduler.animationFrame和fromEvent(window,'scroll')流结合起来?

Observable.fromEvent(window, 'scroll') 
     .map((event: any) => event.currentTarget) 
     .subscribe((event) => { 
     this._renderScrollBar(event); 
     }); 
    let x = 0; 
    Observable.of(0, animationFrame) 
     .repeat() 
     .takeUntil(Observable.timer(1000)) 
     .subscribe(() => console.log(x++)); 
} 
+0

我不认为有任何简单的方法来运行在RxJS每animationFrame动作。 – martin

+0

是[zip](http://reactivex.io/documentation/operators/zip.html)您正在查找的行为? – concat

+0

@concat我认为你能够在答案中做出样本?我会试试看,并将其标记为正确 –

如果要将滚动事件调整为requestAnimationFrame,则可以使用throttleTime(0, animationFrame)运算符而不是Observable.of(0, animationFrame)

Observable.fromEvent(window, 'scroll') 
    .throttleTime(0, animationFrame) 

zip是一个快速和肮脏的解决方案,具有潜在的严重缺陷:真正的滚动值背后的滚动处理滞后滚动时发出的事件比帧速率更快。它看起来是这样的:

Observable.fromEvent(window, 'scroll') 
      .map(event => event.currentTarget) 
      .zip(Observable.of(0, animationFrame) 
         .repeat(), 
      (currentTarget, _) => this._renderScrollBar(currentTarget) 
     ); 

如果需要event包含了最新的滚动信息,你可能需要求助于更复杂的解决方案与the window operator,如:

Observable.fromEvent(window, 'scroll') 
      .map(event => event.currentTarget) 
      .window(Observable.of(0, animationFrame).repeat()) 
      .mergeMap(w => w.takeLast(1)) 
      .subscribe(currentTarget => this._renderScrollBar(currentTarget)); 
  1. 至上,window从源创建一个Observable块,每次参数Observable发出一个项目时都会分块。在这种情况下,一系列滚动事件由每个动画片段分块。
  2. 如果块不为空,我们只取每块的最新版本,并将mergeMap修改为平面输出流。空的块将不会贡献任何项目到这最后的流。
+0

它似乎正在工作,但我得到一个错误 EmptyError {名称:“EmptyError”,堆栈:“EmptyError:序列中没有元素,消息:”序列中没有元素“ } 消息 : “在序列中没有元素” 名 : “EmptyError” 栈 : “EmptyError:按顺序 –

+0

没有元素@MatthewHarwood我的坏,'takeLast(1)'是你想要的,如不会抛出空的流。 – concat