2016-09-28 54 views
1

這裏是鏈:observableOne.flatMap(event -> observableTwo).subscribe()以事件後,才從鏈可觀察到的已發出一個

我想借此事件從observableOne的第一次它發出一個,則忽略此Observable所有其他事件直到observableTwo已發出一個值,完成或完成一個錯誤。值得一提的是,我最終對第二個Observable的事件感興趣。

上下文相似,有一個Button點擊哪個事件被觸發,這是ObservableOne。被觸發的事件觸發ObservableTwo,假設它是一系列網絡操作。所以我想在執行網絡操作時忽略所有按鈕點擊。

+0

如果多次單擊按鈕,通常會忽略先前的網絡操作 - 只會在最後一次按鈕單擊時獲取網絡操作的結果。爲什麼選擇忽略按鈕點擊直到當前的網絡操作完成? – Enigmativity

+0

你似乎已經結束了這個問題。爲什麼不在收到點擊後禁用按鈕,並在處理網絡操作結果後重新啓用它? – JohnWowUs

+0

這只是更復雜的邏輯的一部分,有一個原因 – Eugene

回答

0

來控制flatMap提出的請求量使用特殊的過載:

observableOne 
    .doOnRequest(System.out::println) 
    .flatMap(event -> observableTwo, 1) 
    .flatMap(event -> observableThree, 1) 
.subscribe() 

如果你的源代碼observableOneobservableTwoobservableThree是同步的這不應該是必要的,但對於異步資源本應做的工作。

+0

我更新了描述,因爲它不是很清楚。 – Eugene

0

[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(); 
      } 
     ); 
} 
  • 使用onErrorReturn()(用doOnError()結合實際做一些事情)

    • 重新訂閱

      AtomicBoolean progress = new AtomicBoolean(); 
      observableOne 
          .filter(event -> !progress.get()) 
          .flatMap(event -> 
            observableTwo 
              .doOnSubscribe(() -> progress.set(true)) 
              .doOnTerminate(() -> progress.set(false)) 
              .doOnError(error -> handleError(error)) 
              .onErrorReturn(null) 
              .filter(data -> data != null) 
          ) 
          .subscribe(data -> handleResponse(data)); 
      

    如果您需要,請記得使用subscribeOn()/observeOn()以及正確的調度程序。

    請考慮用switchMap()代替flatMap() - >如果再次按下該按鈕,先前的呼叫被取消(取消訂閱),然後開始新的呼叫。或者用Rx來表示:observableTwo先前的訂閱已取消訂閱,並且形成了新的訂閱。

    如果您在取消訂閱時禁用了您的按鈕並在終止時啓用了它,您可以通過使按鈕不可點擊來輕鬆獲得相同的結果。

  • +0

    我更新了描述,因爲確實很笨拙。 – Eugene

    +0

    對不起,我已經更新了我的答案,但它仍然不正確,額外的數字不工作,因爲我期望:-(它只是延遲映射 –

    +0

    現在它是正確的,但需要一個狀態標誌,這意味着不是100%反應:) –

    相關問題