RxJS:(时间)下一次发射后开始的缓冲区

RxJS:(时间)下一次发射后开始的缓冲区,rxjs,rxjs5,Rxjs,Rxjs5,我想知道如何用RxJs(4/5)正确地实现这一点 我认为: .buffer(source$.throttleTime(5000).debounceTime(5000)) 在rxjs 5中完成这项工作,最好的办法是使用缓冲区。缓冲区有一个关闭条件,您希望在引入新项5秒后有一个关闭条件。因此,假设您有一个源流,您想要的流将是: source.buffer(source.throttle(5100).debounce(5000)); 这是RXJS4。我认为rxjs有一个稍微不同的缓冲操作符,但想法

我想知道如何用RxJs(4/5)正确地实现这一点

我认为:

.buffer(source$.throttleTime(5000).debounceTime(5000))

在rxjs 5中完成这项工作,最好的办法是使用缓冲区。缓冲区有一个关闭条件,您希望在引入新项5秒后有一个关闭条件。因此,假设您有一个源流,您想要的流将是:

source.buffer(source.throttle(5100).debounce(5000));
这是RXJS4。我认为rxjs有一个稍微不同的缓冲操作符,但想法是一样的

说明: 油门确保在5100毫秒内,您将只获得第一个“滴答声”。去抖动将在5000毫秒后传播此“滴答声”,因为此后没有其他“滴答声”。请注意,我选择了5100毫秒,因为计时并不总是完美的,如果两者都使用5000毫秒,则去抖动可能会重复延迟,并且您会挨饿。无论如何,您的缓冲区不会丢失数据,只是可能将其分组为大于5000毫秒的数据块


Rxjs 5有一个bufferToggle操作符,它看起来可能是一个更好的选项,但是,您打开和关闭缓冲区的事实可能会有风险,并且由于时间问题,使您的数据丢失。

尝试了所有Rxjs 5缓冲区变体,特别是每n秒发出一次空或不空的bufferTime,我最终把我自己的缓冲带卷了起来:

function bufferTimeLazy(timeout) {
  return Rx.Observable.create(subscriber => {
    let buffer = [], hdl;
    return this.subscribe(res => {
      buffer.push(res);
      if (hdl) return;

      hdl = setTimeout(() => {
        subscriber.next(buffer);
        buffer = [];
        hdl = null;
      }, timeout);

    }, err => subscriber.error(err), () => subscriber.complete());
  });
};

// add operator
Rx.Observable.prototype.bufferTimeLazy = bufferTimeLazy;

// example
const click$ = Rx.Observable.fromEvent(document, 'click');

click$.bufferTimeLazy(5000).subscribe(events => {
  console.log(`received ${events.length} events`);
});
例如:

其思想是在缓冲区中收集事件,并在第一个事件发生n秒后发出缓冲区。一旦发出,清空缓冲区并保持休眠状态,直到下一个事件到达

如果您不希望将运算符添加到Observable.prototype,只需调用函数:

bufferTimeLazy.bind(source$)(5000)
编辑: 好的,所以Rxjs 5并不都是坏的:

var clicks = Rx.Observable.fromEvent(document, 'click').share();
var buffered = clicks.bufferWhen(() => clicks.delay(5000));
buffered.subscribe(x => console.log(`got ${x.length} events`));

达到同样的效果。注意share()以避免重复的点击订阅-YMMV。

我使用的是RxJS 6,无法轻松找到5的文档。然而,这是一个奇妙的问题。这是我的结果,在一个用角材料复制bug的例子中也得到了证明

source$ = source$.pipe(buffer(source$.pipe(debounceTime(5000))));

正如Trevor所提到的,在RXJS 6中没有正式的方法,但显然需要使用
debounce+buffer
,以实现该结果

为了正确地处理问题,在Typescript和类型推断中,我创建了一个名为
bufferDebounce
的自定义运算符Function,它使该运算符更易于使用和理解

具有类型推断的代码段

type BufferDebounce=(debounce:number)=>OperatorFunction;
常量bufferDebounce:bufferDebounce=debounce=>source=>
新的可观察对象(观察者=>
source.pipe(缓冲区(source.pipe(debounceTime(debounce))).subscribe({
下一(x){
观察员:下一个(x);
},
错误(err){
观察者错误(err);
},
完成(){
observer.complete();
},
})
//[在500ms内无排放之前,尽可能多的源]
source.pipe(bufferDebounce(500)).subscribe(console.log)

您可以在这个工作示例中尝试它:

谢谢,有点像是
.buffer(source$.throttleTime(5000))
做这项工作我不确定,如果您的流是连续的,它会继续,但是如果您有一个暂停,最后的元素将被挂起,直到下一个节流。节流在上升信号(第一个元素)上滴答一声,在最后取消盎司。
source$ = source$.pipe(buffer(source$.pipe(debounceTime(5000))));