Rx java Rx中的即时去盎司

Rx java Rx中的即时去盎司,rx-java,rxjs,system.reactive,debounce,Rx Java,Rxjs,System.reactive,Debounce,我正在寻找一个操作符来消除一系列事件,比如说用户的点击。输入和输出应如下所示: interval : -> <- -> <- in : 1--2--3-------4--5--5--6-7-8-------- out : 1-------------4--------------------- interval:->因为debounce()本质上是异步的,所以需要显式地将结果返回到当前线程 serie

我正在寻找一个操作符来消除一系列事件,比如说用户的点击。输入和输出应如下所示:

interval :      ->     <-            ->     <-
in       : 1--2--3-------4--5--5--6-7-8--------
out      : 1-------------4---------------------
interval:->因为
debounce()
本质上是异步的,所以需要显式地将结果返回到当前线程

seriesOfUnfortunateEvents
  .debounce( 14, TimeUnit.MILLISECONDS )
  .observeOn( Schedulers.immediate() )
  .subscribe( v -> yourStuff() );
据介绍,RxJS中有两个去盎司操作符。您可能特别对
debounceTime
感兴趣

debounceTime
来自文档

仅在经过特定时间跨度且没有其他源发射后,才从源发射可观测的值

例如:

Rx.Observable
    .fromEvent(document.querySelector('button'), 'click')
    .debounceTime(200)
    .mapTo(() => 'clicked!')
    .subscribe(v => console.log(v));
它会发出一声咔嗒声!如果在给定的时间跨度内(本例中为200ms)单击按钮

debounce
来自文档

仅在特定时间后从源发出可观察的值 由另一个可观察物确定的跨度已经过去,没有另一个可观察物 源排放


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

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


请参阅。

编辑:根据澄清,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()))
            );
    }
}
import java.util.concurrent.TimeUnit;
进口接收。可观察;
公共类DebounceFirst{
公共静态void main(字符串[]args){
可观察的。刚好(0,100,200,1500,1600,1800,2000,10000)
.flatMap(v->Observable.timer(v,TimeUnit.millides).map(w->v))
.doOnNext(v->System.out.println(“T=“+v))
.compose(去BounceFirst(500,时间单位毫秒))
.toBlocking()
.subscribe(v->System.out.println(“取消公告:+v”);
}
静态可观察。变压器去BounceFirst(长超时,时间单位){
返回f->
f、 发布(g->
g、 采取(1)
康卡特维思先生(
g、 开关映射(u->Observable.timer(超时,单位).map(w->u))
.采取(1)
.ignoreElements()
)
.repeatWhen(h->h.takeUntil(g.ignoreElements()))
);
}
}

这非常接近,但是让我们假设我想要的间隔是
yb
也比
bx
长,
xc
xc
我希望输出只包含
a
b
@QuangLinhLe您可以设置任何您想要的间隔。或者我不明白你想要什么…我刚刚编辑了这个问题,时间间隔是从最后两次
点击开始的,不是从开始开始的。我仍然认为你准确地描述了
油门的功能。请纠正我我的假设是错的。使用
油门
并延迟5秒,如果用户重复单击按钮,我将在500秒内收到大约100次单击?我想要的只是第一个。谢谢@Michal,我想要的是当我点击按钮时,有一个
点击
事件,然后每隔
点击
一次,直到最后两次
点击
的间隔超过200秒谢谢@akarnokd。这是正确的实现。我真的很喜欢你的测试代码,并偷了它作为我的答案之一。是的,
compose
的想法非常好@有没有可能向我们解释一下你是如何设计出这个工具的?@akarnokd我们可以把它添加为操作员。它感觉像是一个常见的用例,没有找到答案就很难正确实现;您必须非常深入地了解RxJava操作符,并了解底层数据流,才能将这些不同的操作符组合在一起@FriendlyMikhail这是一个不常见的操作符,因为去抖动超时必须一次又一次地延长。也许你可以让rxjava额外人员把它拿到1.x版。2.x在RxJava2Extensions中有此功能。是相关的。