2017-08-17 21 views
0

我正在使用Spring反應堆3.1.0.M3,並有一個用例,我需要合併來自多個源的單聲道。我發現如果其中一個Monos是空的Mono,zip會失敗而不會出錯。彈簧反應堆:Mono.zip在空單聲道上失敗

實施例:

Mono<String> m1 = Mono.just("A"); 
Mono<String> m2 = Mono.just("B"); 
Mono<String> m3 = Mono.empty(); 

Mono<String> combined = Mono.zip(strings -> { 
    StringBuffer sb = new StringBuffer(); 
    for (Object string : strings) { 
     sb.append((String) string); 
    } 
    return sb.toString(); 
}, m1, m2, m3); 
System.out.println("Combined " + combined.block()); 

當添加m3時,組合子被跳過在響應爲空。當我刪除m3時,它全部按預期工作,並返回「AB」。 有沒有辦法通過檢測空的Mono來處理這個問題? 另外,有沒有辦法讓combinator方法知道對象的類型,而不是必須轉換?

+0

對於少數單聲道有Mono.when(我們實際上正在考慮將它改爲3.1.0中的zip)。它不會改變empy-if-one-source-empty行爲,儘管... –

+0

在這個例子中,我只有3個Mono,但在實際的代碼中我使用了Iterable。所以如果我可以過濾掉空的單聲道或以某種方式處理它,這將是有用的。目前,組合的單聲道解決方案無效,並沒有指出原因。當Mono's由多個來源生產時,不能保證沒有任何將是空的 – athom

回答

1

zip操作符的行爲不像這樣。這實際上是違反直覺的:你的代碼期望有3個元素的Tuple,而你只能得到兩個?!?

在這種情況下,您可以控制,只有您可以決定什麼是默認值(如果沒有提供)(請記住,null值被反應流規範禁止)。

Mono<String> m1 = Mono.just("A"); 
Mono<String> m2 = Mono.just("B"); 
Mono<String> m3 = Mono.empty().defaultIfEmpty(""); 

Mono<String> combined = Mono.when(m1, m2, m3).map(t -> { 
    StringBuffer sb = new StringBuffer(); 
    sb.append(t.getT1()); 
    sb.append(t.getT2()); 
    sb.append(t.getT3()); 
    return sb.toString(); 
}); 

編輯

你似乎由Publisher類型的性質相混淆,請參閱:

如果MONOS型的一個是空單,拉鍊失敗,沒有一個錯誤

and

所以,如果我是試圖壓縮Mono的出於某種原因,一個是空的,拉鍊會失敗,我似乎無法把任何代碼,以防止該

Mono是不是一個失敗案例:這只是沒有價值發射,它已成功完成。您可以驗證通過改變代碼示例:

combined.subscribe(
      s -> System.out.println("element: " + s), // doesn't execute 
      s -> System.out.println("error: " + s), // doesn't execute 
      () -> { System.out.println("complete!"); // prints 
    }); 

所以根據您的要求,您可以:

  • 應用defaultIfEmpty運營商在這些3種Mono情況下,如果有,你可以方便的默認值依靠
  • 所述組合Mono施加defaultIfEmpty操作者,具有缺省值或甚至變換到錯誤消息與combined.switchIfEmpty(Mono.error(...))
+0

我想了解如何在不受我控制的Mono 的多個生產者的環境中工作。因此,如果我嘗試壓縮Mono,而且由於某種原因,其中一個是空的,則zip會失敗,我似乎無法輸入任何代碼來防止這種情況發生。 我使用的反應堆3.1.0.M3似乎沒有與你的樣品中的簽名壓縮 – athom

+0

我編輯了我的答案強調,一個空的單聲道不是失敗案例 –