如何使用基于值的去抖流?

时间:2017-04-27 17:23:51

标签: rxjs reactive-programming reactive-extensions-js

例如,假设我们有像下面的流

Stream 1 | -1-2-3-1-2-3--4-----------
去抖后,我希望发出的流如下所示:

Stream 2 | ---------------1-2-3--4------

有许多示例如何去抖动流,但它们将所有值视为相同的触发器。

以下是我在reactitve-extension网站上找到的示例代码,

var Rx = require('rxjs/Rx');
var times = [
    { value: 1, time: 100 },
    { value: 2, time: 200 },
    { value: 3, time: 300 },
    { value: 1, time: 400 },
    { value: 2, time: 500 },
    { value: 3, time: 600 },
    { value: 4, time: 800 }
];

// Delay each item by time and project value;
var source = Rx.Observable.from(times)
  .flatMap(function (item) {
    return Rx.Observable
      .of(item.value)
      .delay(item.time);
  })
  .debounceTime(500 /* ms */);

var subscription = source.subscribe(
  function (x) {
    console.log('Next: %s', x);
  },
  function (err) {
    console.log('Error: %s', err);
  },
  function () {
    console.log('Completed');
  });

控制台输出将是

Next: 4
Completed

但我想获得以下输出

Next: 1
Next: 2
Next: 3
Next: 4
Completed

Maxime给出了很好的答案。 我也试试自己。希望帮助有同样问题的人。

var Rx = require('rxjs/Rx');
var times = [
    { value: 1, time: 100 },
    { value: 2, time: 200 },
    { value: 3, time: 300 },
    { value: 1, time: 400 },
    { value: 2, time: 500 },
    { value: 3, time: 600 },
    { value: 4, time: 800 },
    { value: 5, time: 1500 }
];

// Delay each item by time and project value;
var source = Rx.Observable.from(times)
  .flatMap(function (item) {
    return Rx.Observable
      .of(item.value)
      .delay(item.time);
  })
  .do(obj => console.log('stream 1:', obj, 'at', Date.now() - startTime, `ms`))
  .groupBy(obj => obj)
  .flatMap(group => group.debounceTime(500))

let startTime = Date.now();
var subscription = source.subscribe(
  function (x) {
    console.log('stream 2: %s', x, 'at', Date.now() - startTime, 'ms');
  },
  function (err) {
    console.log('Error: %s', err);
  },
  function () {
    console.log('Completed');
  });

控制台将输出

stream 1: 1 at 135 ms
stream 1: 2 at 206 ms
stream 1: 3 at 309 ms
stream 1: 1 at 409 ms
stream 1: 2 at 509 ms
stream 1: 3 at 607 ms
stream 1: 4 at 809 ms
stream 2: 1 at 911 ms
stream 2: 2 at 1015 ms
stream 2: 3 at 1109 ms
stream 2: 4 at 1310 ms
stream 1: 5 at 1510 ms
stream 2: 5 at 1512 ms
Completed

1 个答案:

答案 0 :(得分:1)

这是我建议的代码:

const { Observable } = Rx

const objs = [
  { value: 1, time: 100 },
  { value: 2, time: 200 },
  { value: 3, time: 300 },
  { value: 1, time: 400 },
  { value: 2, time: 500 },
  { value: 3, time: 600 },
  { value: 4, time: 800 }
];

const tick$ = Observable.interval(100)

const objs$ = Observable.from(objs).zip(tick$).map(x => x[0])

objs$
  .groupBy(obj => obj.value)
  .mergeMap(group$ => 
    group$
     .debounceTime(500))
  .do(obj => console.log(obj))
  .subscribe()

输出与预期一致:

enter image description here

这是一个带有演示的Plunkr工作 https://plnkr.co/edit/rEI8odCrhp7GxmlcHglx?p=preview

说明:

我尝试制作一个小型架构:enter image description here

问题是,您无法直接在主要观察对象上使用debounceTime(这就是为什么您只有一个值)。您必须使用groupBy运算符对自己的流中的每个值进行分组,并将debounceTime应用于分割的值组(我试图在图像中显示)。然后使用flatMapmergeMap获取最后一个流。

文件:
以下是一些可能有助于您理解的页面:
  - groupBy
  - debounceTime
  - mergeMap