Rx java RxJava-与switchMap()运算符相反?

Rx java RxJava-与switchMap()运算符相反?,rx-java,reactive-programming,Rx Java,Reactive Programming,我想知道是否有一种方法可以组合现有的操作符来执行与switchMap()相反的操作 switchMap()将跟踪它接收到的最新发射,并取消它以前执行的任何可观察到的。假设我翻转了它,我想忽略xxxMap()操作符在忙于接收第一次发射时到达的所有发射。它将一直忽略发射,直到它完成发射其内部可观测的当前。然后,它将处理接收到的下一次发射 Observable.interval(1, TimeUnit.SECONDS) .doOnNext(i -> System.out.prin

我想知道是否有一种方法可以组合现有的操作符来执行与
switchMap()
相反的操作

switchMap()
将跟踪它接收到的最新发射,并取消它以前执行的任何可观察到的
。假设我翻转了它,我想忽略
xxxMap()
操作符在忙于接收第一次发射时到达的所有发射。它将一直忽略发射,直到它完成发射其内部可观测的当前
。然后,它将处理接收到的下一次发射

Observable.interval(1, TimeUnit.SECONDS)
        .doOnNext(i -> System.out.println("Source Emitted Value: " + i))
        .ignoreWhileBusyMap(i -> doIntensiveProcess(i).subcribeOn(Schedulers.computation())) 
        .subscribe(i -> System.out.println("Subscriber received Value: " + i));

有没有办法做到这一点?在上述示例中,如果
intensiveProcess()
持续三秒,则
ignoreWhileBusyMap()
将处理
0
,但可能忽略来自
interval()
的排放
1
2
。然后它将处理
3
,但可能忽略
4
5
,以此类推……

当然,在处理完成后,通过设置的布尔值对值的处理进行选通:

AtomicBoolean gate = new AtomicBoolean(true);

Observable.interval(200, TimeUnit.MILLISECONDS)
.flatMap(v -> {
    if (gate.get()) {
        gate.set(false);

        return Observable.just(v).delay(500, TimeUnit.MILLISECONDS)
                .doAfterTerminate(() -> gate.set(true));
    } else {
        return Observable.empty();
    }
})
.take(10)
.toBlocking()
.subscribe(System.out::println, Throwable::printStackTrace);
编辑

备选方案:

Observable.interval(200, TimeUnit.MILLISECONDS)
.onBackpressureDrop()
.flatMap(v -> {
    return Observable.just(v).delay(500, TimeUnit.MILLISECONDS);
}, 1)
.take(10)
.toBlocking()
.subscribe(System.out::println, Throwable::printStackTrace);

您可以将
onBackpressureDrop
更改为
onBackpressureLatest
以立即使用最新值继续操作。

以回答危险样式:什么是
concatMap

concatMap
将订阅第一个
Observable
,并且在前一个
Observable
调用
onComplete()
之前,不会订阅后续的
Observable
s

在这方面,它是
switchMap
的“反面”,当一个新的
observed
s出现时,它会急切地取消订阅以前的
observed
s


concatMap
希望听到每个可观察对象所说的一切,而
switchMap
是一只社交蝴蝶,一旦另一个可观察对象可用,它就会继续前进。

我知道这是一个旧线程,但目前有一个RxJs操作符可以做到这一点

操作员正在
exhaustMap

根据报告:

ExhaustMap将每个源值投影到一个可观测值,只有在前一个投影可观测值已完成时,该值才会合并到输出可观测值中

文件:


太棒了,我对一个
信号量做了类似的事情,但希望对现有的操作符使用一个纯粹的反应合成。我想我可以用一个
Transformer
来包装所有这些。使用一个延迟的Transformer来避免在多个终端订阅者之间共享网关。不过我刚刚意识到你的解决方案不像我的解决方案那样是block-y,所以我将切换到这个。谢谢哈哈,是的,这次我会记住:)不会再犯那个错误了,谢谢你的选择。我能够将它组合成Kotlin的一个扩展函数:
inline fun Observable.ignoreWhileBusyMap(crossinline mapper:(T)->Observable)=onBackpressureDrop().flatMap({mapper.invoke(it)},1)
不太好,如果你仔细阅读这个问题,你会发现我追求的行为与
concatMap
或其感知的对立面关系不大。按照你的类比,我正在寻找一个
xxxMap
操作符,它将专注于与它遇到的第一个可观测对象对话,并告诉任何后续的可观测对象“不是现在,我正忙着与这个家伙对话”。只有当他的对话结束时,他才会允许另一个观察者与他接触。这就是
concatMap
所做的。我相信
concatMap()
flatMap()
相同,但它不会交错。它保证所有排放物最终都会被排放,即使它将排放物排队。但我要求的运营商只是在忙的时候忽略后续的排放。啊,好吧,我认为你说的“忽略排放”是指“现在忽略排放”,但正如你问题的最后一段所述:这些排放应该减少。在这种情况下,我喜欢akarnokd提出的解决方案。这是目前最好的答案,因为当原始答案被接受时,排气地图并不存在。排气地图在RxJava中仍然不存在,这是最初提出的问题。我很失望RxJava没有它,因为它来自RxJs。
import { fromEvent, interval } from 'rxjs';
import { exhaustMap, take } from 'rxjs/operators';

const clicks = fromEvent(document, 'click');
const result = clicks.pipe(
  exhaustMap(ev => interval(1000).pipe(take(5)))
);
result.subscribe(x => console.log(x));