问题
I get the feeling that I am misusing the CompletableFuture API.
When invoking CompletableFuture.exceptionally()
I routinely find myself needing to invoke another asynchronous process, which means that exceptionally()
returns CompletableFuture<CompletableFuture<T>>
instead of CompletableFuture<T>
. I then cast the result back using thenCompose(x -> x)
.
Here is a concrete example:
CompletableFuture<Void> listenersNotified = CompletableFuture.supplyAsync(() ->
{
int result = expensiveOperation();
List<CompletionStage<Void>> futures = new ArrayList<>();
for (EventListener listener: listeners)
listener.onSuccess(result);
return futures;
}).thenCompose(futures -> CompletableFuture.allOf(futures)).
exceptionally((exception) ->
{
List<CompletionStage<Void>> futures = new ArrayList<>();
for (EventListener listener: listeners)
futures.add(listener.onError(result));
return CompletableFuture.allOf(futures);
}).thenCompose(x -> x);
I understand that in the above example, one can return futures
from inside exceptionally()
and move thenCompose()
after exceptionally()
and this will work, but in real-life I don't always want to apply the same function to the result of thenSupply()
as the result of exceptionally()
. I want each section to take care of converting its own return type from a CompletableFuture
to a synchronous value.
Is there a way to avoid falling into this pattern?
来源:https://stackoverflow.com/questions/51217350/how-to-avoid-invoking-completablefuture-thencomposex-x