问题
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