此问题特定于 Java 和 CompletableFuture
。
如果我有如下所示的异步方法,
CompletableFuture<String> get() {
/* Step #1: Do some sync prep work */
String s = doSomethingSync();
/* Step #2: Do something async (returning CompletableFuture) */
return doSomethingAsync(s);
}
如果步骤 #1 中的代码抛出异常,get()
的调用方将在获取其返回的 CompletableFuture
之前收到异常,而如果步骤 #2 中返回的 CompletableFuture
内的代码抛出异常,则调用方仅在与返回的 CompletableFuture
交互时才会收到异常。
这表明 get()
的调用者应该编写一些复杂的异常处理代码来处理这两种情况。
下面是另一个异步方法 invokeGet()
的示例,该方法调用 get()
并返回其返回的 String
的长度:
CompletableFutre<Integer> InvokeGet() {
try {
CompletableFuture future = get();
return furure.handle((result, throwable) -> {
if (throwable != null) {
/* Handle exception thrown in step #2 in get(), e.g. rethrow */
} else {
return result.length();
}
});
} catch (Exception e) {
/* Handle exception thrown in step #1 in get() */
/* Return some value or throw */
}
}
我的问题是:
get()
是否写得不好,因为它要求调用者进行这种复杂的异常处理,还是这是一种常见的模式?返回 CompletableFuture 的异步方法是否应该将自己限制为在出现错误时返回错误的 future,以便其调用者不必编写此类错误处理代码?
最佳答案
简而言之,这取决于您自己的实现,但可以改进。如果您想通过不同的线程忽略、记录或响应异常(基本示例 here ),则让调用线程处理异常可能会很有帮助。然而,我见过的很多模式(在this posts answer中看到)会让您包含带有try-catch-block
的async
函数,并重新抛出一个对您的应用程序更有用的异常,由父线程处理,我认为这更好一点。
如果您正在寻找不同的异常处理,请参阅此 article 以获取不同处理的示例。
关于java - 从返回 CompletableFuture 的异步方法的同步部分抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51883520/