我在玩CompletableFuture連鎖店,偶然發現了意外行爲的情況(至少對我來說):如果在.thenCompose()
調用中傳遞了一個例外的CompletableFuture,則生成的CompletableFuture將完成原始異常包裝在CompletionException
。這可能是很難理解沒有一個例子:強制執行期望的CompletableFuture行爲
public static <T> CompletableFuture<T> exceptional(Throwable error) {
CompletableFuture<T> future = new CompletableFuture<>();
future.completeExceptionally(error);
return future;
}
public static void main(String[] args) {
CompletableFuture<Void> exceptional = exceptional(new RuntimeException());
exceptional
.handle((result, throwable) -> {
System.out.println(throwable);
// java.lang.RuntimeException
System.out.println(throwable.getCause());
// null
return null;
});
CompletableFuture
.completedFuture(null)
.thenCompose(v -> exceptional)
.handle((result, throwable) -> {
System.out.println(throwable);
// java.util.concurrent.CompletionException: java.lang.RuntimeException
System.out.println(throwable.getCause());
// java.lang.RuntimeException
return null;
});
}
我當然期待處理相同RuntimeException
無論之前或之後鏈條多少的轉化都。我有兩個問題:
- 是否預期行爲?
- 除了手動解包外,我有任何選項可以讓原始異常通過嗎?