在 CompletableFutures 中捕获异常的最佳实践

问题描述 投票:0回答:1

我经常发现返回 CompletableFuture 的库方法,并且函数签名中也有

throws Exception
。据我了解,这些函数中抛出的异常不会被 try-catch 捕获,因为 future 通常要等到代码离开 try-catch 块很久之后才会完成。因此,我们被告知将
.exceptionally()
附加到 CompletableFuture 链来处理这些失败。

所以我希望能够这样写:

CompletableFuture<Void> libFunction() throws Exception;

CompletableFuture<Void> caller() {

  return libFunction()
    .exceptionally(exception -> {
      // code to handle exception
    }) 
}

问题是 java 要求 caller() 在 libFunction 调用周围包含一个 try-catch 块,或者让 caller() 在其签名中包含

throws Exception
。如果我包含一个 try-catch,则相当于编写一些无用的异常处理代码,这些代码永远不会被调用,并且对于异常块中的代码来说是多余的。

另一个选项是将

throws Exception
添加到我的函数签名中。但这意味着调用链中的每个函数,直到调用 .join() 之前,都需要在其签名中包含
throws Exception
。而且事实上,该函数实际上永远不会抛出异常,因为如果抛出异常,CompletableFuture 会将异常包装在 CompletionException 中,并将其传递给 .exceptionally。 所以我的问题是如何使用 CompletableFuture 编写良好的异步代码,而不需要将不必要的异常添加到我的所有函数签名或冗余的 try-catch 块中以满足编译器的要求?

更新:更多上下文 - 我使用一个框架,该框架自动生成与 gRPC 服务路由相关的签名。这些签名本身返回 CompletionStage。因此从技术上讲,连接是由框架调用的,而不是由我调用。因此,由于顶级函数签名是自动生成的,因此仅将异常冒泡到发生连接的位置是不切实际的。

java exception completable-future
1个回答
0
投票

感谢@rogue 和@david-conrad 帮助我理解这一点。

© www.soinside.com 2019 - 2024. All rights reserved.