我想知道如何使用RxJs(4/5)正确实现这个?
-a-- -b----c----d-----------------------------------------------------------e------f---------------------
-5-sec after-"a"--> [abcd]---new 5 sec timer will start when "e" emited-----5 sec-after-"e"->[ef]-
我想这个:
.buffer(source$.throttleTime(5000).debounceTime(5000))
在rxjs 5中完成这项工作
答案 0 :(得分:1)
你最好的拍摄是使用缓冲区。缓冲区具有关闭条件,并且您希望在引入新项目5秒后关闭条件。所以,假设你有一个源流,你想要的流将是:
source.buffer(source.throttle(5100).debounce(5000));
这是rxjs 4.我认为rxjs的缓冲区运算符略有不同,但想法是一样的。
说明: 节流阀确保对于5100 mSecs,您将只获得第一个“滴答”。去抖动将在5000 mSecs之后传播这个“滴答声”,因为之后没有其他“滴答声”。请注意,我选择5100 mSecs,因为时间并不总是完美的,如果你使用5000 mSecs,去抖可能会反复延迟,你会得到饥饿。无论如何,你的缓冲区不会丢失数据,只是将它分成大于5000 mSecs的块。
Rxjs 5有一个bufferToggle运算符,它可能看起来更好,但是,打开和关闭缓冲区这一事实可能会带来风险,并且会因时序问题而导致数据丢失。
答案 1 :(得分:0)
尝试了所有Rxjs 5缓冲区变体,特别是每隔n秒发出空缓冲区的bufferTime,我最终滚动了自己的bufferTimeLazy:
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`);
});
实施例: https://jsbin.com/nizidat/6/edit?js,console,output
想法是在缓冲区中收集事件并在第一个事件发生后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。
答案 2 :(得分:0)
我正在使用RxJS 6,无法轻松找到5的文档。但是,这是一个奇妙的问题。这是我的结果,在real example中再现了Angular Material中的错误。
source$ = source$.pipe(buffer(source$.pipe(debounceTime(5000))));
答案 3 :(得分:0)
正如Trevor所提到的那样,在RXJS 6中没有官方的方法,但是显然您需要使用debounce + buffer
才能获得该结果。
为了正确处理,在Typescript中并使用类型推断,我创建了一个名为 bufferDebounce
的自定义 OperatorFunction ,它使使用和理解起来更加容易运算符。
具有类型推断的代码段
type BufferDebounce = <T>(debounce: number) => OperatorFunction<T, T[]>;
const bufferDebounce: BufferDebounce = debounce => source =>
new Observable(observer =>
source.pipe(buffer(source.pipe(debounceTime(debounce)))).subscribe({
next(x) {
observer.next(x);
},
error(err) {
observer.error(err);
},
complete() {
observer.complete();
},
})
// [as many sources until no emit during 500ms]
source.pipe(bufferDebounce(500)).subscribe(console.log)
您可以在下面的示例中进行尝试:https://stackblitz.com/edit/rxjs6-buffer-debounce