20

我正在寻找debounce一系列事件的操作员,让我们说用户的点击。输入和输出应该是这样的:

interval :      ->     <-            ->     <-
in       : 1--2--3-------4--5--5--6-7-8--------
out      : 1-------------4---------------------

这个想法就像带有immediate选项on http://underscorejs.org/#debounce的下划线去抖动。操作符可以以任何支持反应式扩展的语言呈现/实现

编辑:澄清间隔,比如说 5 秒(两个箭头之间的 5 个空格):-> <-

Edit2:一个更容易理解的版本:我有一个用户,他反复点击一个按钮(1、2、3);我想抓住第一个click(1)并忽略其余的。过了一会儿,他累了,休息7秒(比两个箭头之间的5秒间隔还长)继续再次点击按钮(4,5,6,7,8)我想抓住第一个click(4 ) 并忽略其余部分。

如果他在第四个箭头之后点击,我也想抓住那个点击。

Edit3:这是图片可以在原始文章中找到的图像

4

4 回答 4

18

编辑:根据澄清,RxJava 没有此类流的运算符,但它可以由一组重要的其他运算符组成:

import java.util.concurrent.TimeUnit;

import rx.Observable;

public class DebounceFirst {

    public static void main(String[] args) {
        Observable.just(0, 100, 200, 1500, 1600, 1800, 2000, 10000)
        .flatMap(v -> Observable.timer(v, TimeUnit.MILLISECONDS).map(w -> v))
        .doOnNext(v -> System.out.println("T=" + v))
        .compose(debounceFirst(500, TimeUnit.MILLISECONDS))
        .toBlocking()
        .subscribe(v -> System.out.println("Debounced: " + v));
    }

    static <T> Observable.Transformer<T, T> debounceFirst(long timeout, TimeUnit unit) {
        return f -> 
            f.publish(g ->
                g.take(1)
                .concatWith(
                    g.switchMap(u -> Observable.timer(timeout, unit).map(w -> u))
                    .take(1)
                    .ignoreElements()
                )
                .repeatWhen(h -> h.takeUntil(g.ignoreElements()))
            );
    }
}
于 2017-01-31T23:40:59.863 回答
11

您想要的行为不是debounce操作员在 Rx 中所做的。

这称为throttle, throttleTimeor throttleWithTimeout(但是,它属于debounce运算符类别)。我不知道你使用什么语言,但在 RxJS 中它看起来像下图:

在此处输入图像描述

请参阅http://reactivex.io/documentation/operators/debounce.html

于 2017-01-31T19:10:27.120 回答
1

因为debounce()本质上是异步的,所以您需要显式地将结果带回当前线程。

seriesOfUnfortunateEvents
  .debounce( 14, TimeUnit.MILLISECONDS )
  .observeOn( Schedulers.immediate() )
  .subscribe( v -> yourStuff() );
于 2017-01-31T18:30:39.123 回答
1

根据文档,RxJS 中有两个去抖动运算符。你可能特别感兴趣debounceTime

debounceTime

从文档

仅在经过特定时间跨度而没有另一个源发射后,才从源 Observable 发射一个值。

例子:

Rx.Observable
    .fromEvent(document.querySelector('button'), 'click')
    .debounceTime(200)
    .mapTo(() => 'clicked!')
    .subscribe(v => console.log(v));

它会发出一键!如果在给定的时间跨度(本例中为 200 毫秒)内单击了按钮。

debounce

从文档

只有在另一个 Observable 确定的特定时间跨度过去且没有另一个源发射时,才从源 Observable 发射一个值。

于 2017-01-31T18:30:50.360 回答