Immediate debounce in Rx

倾然丶 夕夏残阳落幕 提交于 2019-12-02 23:11:32

Edit: Based on the clarifications, RxJava doesn't have an operator for this type of flow but it can be composed from a non-trivial set of other operators:

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()))
            );
    }
}

The behavior you want is not what debounce operator does in Rx.

This is called throttle, throttleTime or throttleWithTimeout (however, it falls under debounce category of operators). I don't know what language you use but in RxJS it looks like the following image:

See http://reactivex.io/documentation/operators/debounce.html.

Because debounce() is inherently asynchronous, you need to bring the result back to the current thread explicitly.

seriesOfUnfortunateEvents
  .debounce( 14, TimeUnit.MILLISECONDS )
  .observeOn( Schedulers.immediate() )
  .subscribe( v -> yourStuff() );

According to documentation there are two debounce operators in RxJS. You might be interested in debounceTime in particular.

debounceTime

From documentation

Emits a value from the source Observable only after a particular time span has passed without another source emission.

Example:

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

It will emit one clicked! if button was clicked in given timespan (200ms in this example).

debounce

From documentation

Emits a value from the source Observable only after a particular time span determined by another Observable has passed without another source emission.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!