2016-07-28 123 views
0

我正在学习RxJs。我使用Angular2 rc3。 以下流可用,但它给我太多mousemove事件。我想使用时间(节流)或其他控制流来减慢速度。 我该怎么做?如何使用angular 2 + Typescript在RxJs中处理mousemove事件?

移动鼠标流,而不节流

const mouseMove$ = Observable.fromEvent<MouseEvent>(document, 'mousemove'); 

mouseMove$.subscribe(x => console.log(x)); // works great, many {mouse position object} 's 

简单的解决方案:使用节流应该是这样的:

const mouseMove$ = Observable.fromEvent<MouseEvent>(document, 'mousemove'); 
const latestMouseEventEvery1Second$ = mouseMove$.sample(1000); 

latestMouseEventEvery1Second$.subscribe(x => console.log(x)); // error 

- 这样本()操作我已经采取了形式在这里:http://reactivex.io/documentation/operators/sample.html

但是这在角度2 - CLI项目中不起作用。 给了我这个错误:

***Argument of type 'number' is not assignable to parameter of type 'Observable<\any>'*** - notice i've put <\MouseEvent> when casting. 

另一种更强大的方式来达到同样的效果,我觉得可能是流动的: 这将是巨大的,如果我们可以根据收到的物品发送最新mousemove item从另一个流。任何流 - 由我们创造..

例如:

当我们从eachSecond$流(=我们的“控制流”)收到一个新的项目(1,2,3 ......), - 我们发出donwstream(进入mouseMoveEachSecond$) - 从mouseMove$流收到的最新项目。

const eachSecond$ = Observable.timer(0, 1000); // starts at 0 and gives 1,2,3 as values each 1000 milliseconds. 
const mouseMove$ = Observable.fromEvent<MouseEvent>(document, 'mousemove'); 

const mouseMoveEachSecond$ = Observable.merge(eachSecond$,mouseMove$) 
    .some magic operator I can't find() 
    // this could work like this: 
    // many mouse items are coming at a high rate from the mouse stream 
    // only a few items (1,2,3..) are coming form the eachSecond$ stream 
    //the logic: We send downstream **only one mouse item** (the last) for each new item that is coming form the eachSecond$ stream. 
); 

mouseMoveEachSecond$.subscribe(x => console.log(x)); 
// a { mouse position object } = mouse item - only when you move the mouse 
// and no more than one {mouse position object} per second} 

声音很简单。我发现这很难实现 - 形成我所能说的,这是因为应该以某种方式共享流的状态。有一种方法可以告诉已经发送了什么东西。

在mouseMoveEachSecond $中,项目按顺序依次出现。或者是一个数字或一个物体。您需要知道:

  • 这是最后一位time item当您收到新的mouse item
  • 当您收到新的time item时,哪一次是最后的mouse item

这将允许您:

  • 不发送mouse item下游,当鼠标没有在屏幕上移动。
  • 不发送mouse item下游,而没有新的time item从eachSecond $流发布。

这可以使用全局变量来完成。但是,这不是RxJS的做事方式。我不知道如何存储上次发送的项目并在下一步中使用它。 Reduce运算符可以保持状态:从一个项目发布到另一个项目,但我们如何使用该属性来实现此行为?这些流必须被认为是无限的。嗯...应该是这2流合并更简单的方法..也许是太早了。我觉得我的脑子想不想到在流:)

因此奠定明确两个问题:

  1. 这是一些方法来节制角2中的鼠标移动流?
  2. 我可以使用另一个流来控制何时释放鼠标移动项目?如果是的话,这个“控制流”可以是任何流,或者有限制?

太谢谢你了:)

回答

2

你太亲近了!讽刺你的魔术师sample

样本的旧变体(来自RxJS4)被重载并可能以数字为参数。在RxJS5中(与Angular2一起发货的)已经被分割,所以实际上有两个运营商samplesampleTime。后者是一个需要时间参数,并在发射时在给定时间窗口中接受最后一个事件。

const mouseMoveEachSecond$ = mouseMove$.sampleTime(1000); 

前者需要一个Observable作为其唯一参数,并发出最后一个项目每次控制Observable发射接收。

const eachSecond$ = Observable.timer(0, 1000); // starts at 0 and gives 1,2,3 as values each 1000 milliseconds. 
const mouseMove$ = Observable.fromEvent<MouseEvent>(document, 'mousemove'); 

const mouseMoveEachSecond$ = mouseMove$.sample(eachSecond$); 

mouseMoveEachSecond$.subscribe(x => console.log(x)); 
+0

天才答案的人,谢谢! - 我失去了超过5个小时试图做到这一点 - 使用扫描运算符 - 保持各州之间的状态,所有这一切。我很高兴它非常简单。你知道一个快速的方法来扩展到多个控制流吗?就像你在做某件事之前等待多个承诺完成一样? – AIon

+0

没问题!你可以看看使用'zip'或'forkJoin'组合控制流,以便它们只在每个流有值时发出。 – paulpdaniels

相关问题