CompletableFuture 编写异常

Min*_*inn 1 java completable-future

CompletableFutureAPI 允许我们用来thenCompose链接另一个 future:

CompletableFuture<String> future1 = submit("foo");
CompletableFuture<String> future2 = future.thenCompose((result) -> submit(result));
Run Code Online (Sandbox Code Playgroud)

但这仅适用于成功的响应。有没有办法做同样的事情,但还包括异常处理?

例如:

CompletableFuture<String> future1 = submit("foo");
CompletableFuture<String> future2 = future.handleCompose((result, error) -> {
  if (error != null)
    return submit("failure"); // Handle error by doing a different action with the same result (like a fallback)
  else
    return submit(result);
});
Run Code Online (Sandbox Code Playgroud)

我知道你可以这样做whenComplete

CompletableFuture<String> future2 = new CompletableFuture<>();
CompletableFuture<String> future1 = submit("foo");
future.whenComplete((result, error) -> {
  CompletableFuture<String> tmp;
  if (error != null)
    tmp = submit("failure");
  else
    tmp = submit(result);
  tmp.whenComplete((result2, error2) -> {
    if (error2 != null) future2.completeExceptionally(error2);
    else future2.complete(result2);
  });
});
Run Code Online (Sandbox Code Playgroud)

然而,这失去了正确取消的能力,与成功的组合处理相比,这似乎是一个非常“hacky”的解决方案。有没有一种不需要自己扩展 CompletableFuture 类的好方法?

问题是我需要从我的方法返回一个 future,并且它应该能够在任何时间点取消整个过程。

Did*_*r L 6

您可以将handle()返回的 aCompletableFuture与 a结合起来thenCompose(x -> x)

\n
CompletableFuture<String> future2 = future.handle((result, error) -> {\n  if (error != null)\n    return submit("failure"); // Handle error by doing a different action with the same result (like a fallback)\n  else\n    return submit(result);\n})\n.thenCompose(x -> x);\n
Run Code Online (Sandbox Code Playgroud)\n

不幸的是,没有办法避免最后的情况thenCompose()。另请参阅如何避免调用CompletableFuture.thenCompose(x -> x)以及我对此的评论。

\n

编辑:对于Java 12+,现在有exceptionallyCompose(),我将其描述为这个问题\xe2\x80\x99s重复目标的答案

\n

  • 我会简化语法: `future2 = future.handle((result, error) -&gt; error != null? commit("failure"): Submit(result)) .thenCompose(x -&gt; x);` 或者甚至`future2 = future.handle((result, error) -&gt; Submit(error != null? "failure": result)) .thenCompose(x -&gt; x);` 但请注意,这并没有满足“它应该是能够随时取消整个流程”的要求。对生成的 future 调用 cancel 只会取消 `.thenCompose(x -&gt; x)` 步骤。这是“CompletableFuture”流畅 API 的一个普遍问题。 (2认同)