如何发出每个第n个值?

时间:2017-03-20 12:59:26

标签: javascript rxjs reactive-programming rxjs5

我使用mousemove事件创建一个可观察的。

Observable.fromEvent(document, 'mousemove')

我需要每10次发射一次。我该怎么办?

2 个答案:

答案 0 :(得分:5)

我可以想到四种不同的方法:

<强> bufferCount()

action

<强> windowCount()

Observable.range(1, 55)
  .bufferCount(10)
  .map(arr => arr[arr.length - 1])
  .subscribe(val => console.log(val));

<强>反跳()

Observable.range(1, 55)
  .windowCount(10)
  .switchMap(window => window.takeLast(1))
  .subscribe(val => console.log(val));

<强>扫描()

let source = Observable.range(1, 55).publish();

source
  .debounce(val => debounceNotifier)
  .subscribe(val => console.log(val));

let debounceNotifier = source
  .bufferCount(10)
  .publish();
debounceNotifier.connect();

source.connect();

但是,使用Observable.range(1, 55) .scan((acc, val) => { if (acc.length === 10) { acc = []; } acc.push(val); return acc; }, []) .filter(acc => acc.length === 10) .map(acc => acc[acc.length - 1]) .subscribe(val => console.log(val)); 时,它会丢弃最后一个值scan()

查看所有这些的演示:https://jsbin.com/yagayot/14/edit?js,console

答案 1 :(得分:1)

这是一种更简单且相当快的方法,我在RxJS 6上进行了测试:

range(1, 10000000)
  .pipe(
    filter(function(value, index) { 
      return index % 10 === 0; 
    }),
  );

此代码的速度是其他答案https://jsperf.com/observable-nth/1

bufferCountwindowCount的两倍

这可能是因为filter运算符使用了一个简单的计数器,而不必保留最后n个元素的缓冲区。我假设n较大或元素本身较大时,速度甚至更快。使用RxJS 6,您还可以轻松地将其变成自己的自定义运算符:

const takeEveryNth = (n: number) => filter((value, index) => index % n === 0);
// usage: rxjs.range(1, 10000000).pipe(takeEveryNth(10));

这也是官方文档中用于说明如何创建自定义运算符的代码:https://github.com/ReactiveX/rxjs/blob/6.2.2/doc/pipeable-operators.md