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