Rx java 仅在链中的可观察对象发出事件后才获取事件
下面是链:Rx java 仅在链中的可观察对象发出事件后才获取事件,rx-java,reactive-programming,Rx Java,Reactive Programming,下面是链:observeOne.flatMap(事件->observetwo.subscribe() 我想在observateOne第一次发出一个事件时,从该observateOne中获取事件,然后忽略该observateOne中的所有其他事件,直到observateOne发出一个值,完成或完成一个错误。值得一提的是,最终我对第二个观测到的事件感兴趣 上下文类似于,有一个按钮点击触发事件,这是observeOne。触发的事件触发了observetWO,假设它是一个网络操作链。因此,我希望在执行网
observeOne.flatMap(事件->observetwo.subscribe()
我想在observateOne
第一次发出一个事件时,从该observateOne
中获取事件,然后忽略该observateOne
中的所有其他事件,直到observateOne
发出一个值,完成或完成一个错误。值得一提的是,最终我对第二个观测到的事件感兴趣
上下文类似于,有一个
按钮
点击触发事件,这是observeOne
。触发的事件触发了observetWO,假设它是一个网络操作链。因此,我希望在执行网络操作时忽略所有按钮单击。要控制flatMap发出的请求量,请使用特殊的重载:
observableOne
.doOnRequest(System.out::println)
.flatMap(event -> observableTwo, 1)
.flatMap(event -> observableThree, 1)
.subscribe()
如果您的源
observateOne
,observateTo
,observateThree
是同步的,这应该不是必需的,但对于异步源,这应该可以完成工作。[Edit2]问题已更改,因此我调整了我的答案+实际上给出了正确的答案
除了使用状态标志,我看不到其他方法:
AtomicBoolean progress = new AtomicBoolean();
observableOne
.filter(event -> !progress.get())
.flatMap(event ->
observableTwo
.doOnSubscribe(() -> progress.set(true))
.doOnTerminate(() -> progress.set(false))
)
.subscribe();
如果发生错误,您的订阅将被取消,即使再次单击按钮,您也不会再收到任何事件
如果这不是您想要的,您可以:
- 重新订阅错误回调
private void bindRemoteCalls() { if (mySubscription != null) mySubscription.unsubscribe(); AtomicBoolean progress = new AtomicBoolean(); mySubscription = observableOne .filter(event -> !progress.get()) .flatMap(event -> observableTwo .doOnSubscribe(() -> progress.set(true)) .doOnTerminate(() -> progress.set(false)) ) .flatMap(event -> observableTwo, 1) .subscribe( data -> handleResponse(data), error -> { handleError(error); bindRemoteCalls(); } ); }
- 使用
(结合OneErrorReturn()
来实际处理它)doError()
subscribeOn()
/observeOn()
与正确的调度程序一起使用
请考虑使用<代码> SwitcPMAP()/<代码>代替<代码> FLATAPA](< /代码>)>如果再次按下该按钮,则取消先前的调用(未订阅),然后启动新的调用。或者用Rx术语来说:以前的订阅被取消,新的订阅被形成
如果您在取消订阅时禁用按钮,并在终止时启用按钮,您可以通过使按钮不可点击轻松获得相同的结果。您可以使用可流动的
而不是可观察的,,然后您可以使用背压来实现所需的效果(将事件放置到可观察到的终止)通过将flatMap
的maxConcurrency
设置为1
:
observableOne
.toFlowable(BackpressureStrategy.DROP)
.flatMap(event -> observableTwo.toFlowable(BackpressureStrategy.ERROR), 1)
.subscribe();
我贴了一封信
事实证明,阿卡诺克的图书馆中也有一个用于此目的的observateTransformer
。它可以这样使用:
observableOne
.compose(ObservableTransformers.flatMapDrop(event -> observableTwo))
.subscribe();
我更新了描述,因为它确实很笨拙。对不起,我更新了我的答案,但它仍然不正确。额外的数字并不像我预期的那样起作用:-(它只是延迟了映射现在它是正确的,但需要一个状态标志,这意味着不是100%反应:)我更新了描述,因为它不太清楚。如果多次单击按钮,通常会忽略以前的网络操作-仅在最后一次单击按钮时获取网络操作的结果。为什么选择忽略按钮点击直到当前网络操作完成?您似乎将问题复杂化了。为什么不在收到点击后禁用按钮,并在处理网络操作结果后重新启用?这只是更复杂逻辑的一部分,这是有原因的
observableOne
.compose(ObservableTransformers.flatMapDrop(event -> observableTwo))
.subscribe();