rxjs缓冲区,直到新arg到达的超时重置

时间:2017-08-24 04:23:37

标签: function rxjs accumulate debounce

总结:我正在使用Rxjs和一个新手。我希望实现这样一个具有可观察性的场景,但到目前为止还没有运气。

有一个函数loadDetailsFromServer(itemIds),它调用服务器api并传递一些项目ID。这个函数偶尔称为。为了优化服务器调用,这是我想要做的: 在第一次函数调用到达时,触发超时。如果在超时之前任何新函数调用到达,则重置timout以再次启动。当超时启动时,进行服务器调用,并且参数计数重置为零。

这是一张大理石图:

Timer is 4 clicks.
INPUTS IN TIME        1-2---3-4-----5--------6-7--------
loadDetailsFromServer [1,2,3,4]   -      [5]         -[6,7]  

function called with [1,2,3,4] because no more calls after 4 clicks.

提示:这类似于搜索框样本并从服务器获取结果,除了临时值是感兴趣的,并且不会被忽略/跳过。

2 个答案:

答案 0 :(得分:1)

例如,如果你有这样的源Observable:

const Rx = require('rxjs/Rx');
const Observable = Rx.Observable;

const TIMEOUT = 1000;

const source = Observable.range(1, 20)
    .concatMap(v => Observable.of(v).delay(Math.random() * 2000));

然后,您可以使用scan缓冲其值。要使用.merge(bufferNotifier.mapTo(null))重置缓冲区,请执行此操作。然后使用switchMap()我总是等待1000毫秒才能发出forkJoin()。如果它没有"覆盖"另一个Observable是因为新的缓冲区到了:

const bufferNotifier = new Subject();

const chain = source
    .do(undefined, undefined, () => bufferNotifier.complete()) // properly complete the chain
    .merge(bufferNotifier.mapTo(null)) // reset buffer Subject
    .scan((acc, val) => {
        if (val === null) {
            return [];
        }
        acc.push(val);
        return acc;
    }, [])
    .filter(arr => arr.length > 0)
    .switchMap(buffer => { // wait 1s until emitting the buffer further
        return Observable.forkJoin(
            Observable.of(buffer),
            Observable.timer(1000).take(1),
            arr => arr
        );
    })
    .do(() => bufferNotifier.next()) // trigger reset the buffer
    .subscribe(console.log);

这输出例如:

[ 1 ]
[ 2 ]
[ 3, 4 ]
[ 5 ]
[ 6, 7 ]
[ 8, 9, 10, 11, 12 ]
[ 13 ]
[ 14, 15 ]
[ 16 ]
[ 17 ]
[ 18 ]
[ 19, 20 ]

答案 1 :(得分:0)

如果你对马丁的答案有类似的source观察,那么这样的事情可能有效:

source
  .buffer(source.debounceTime(250))
  .subscribe(console.log);

buffer收集所有发出的值,直到给定的observable发出。在这种情况下,它会等到debounceTime发出。 CodePen:https://codepen.io/anon/pen/PKBaZm?editors=1010