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