我正在通过 CompletableFuture 接收来自服务调用的响应。我想处理服务返回的一些已知异常,例如乐观并发控制冲突。
这是我得到的。有没有更好的不包装异常或使用 SneakyThrows 的方法?包装异常意味着其他异常处理程序必须检查因果链,而不是仅仅使用 instanceof
。
someService.call(request)
.handle((response, error) -> {
if (error == null)
return CompletableFuture.completedFuture(response);
else if (error instanceof OCCException)
return CompletableFuture.completedFuture(makeDefaultResponse());
CompletableFuture<Response> errorFuture = new CompletableFuture<>();
errorFuture.completeExceptionally(error);
return errorFuture;
}).thenCompose(Function.identity());
同样,有没有一种方法可以在不使用 wrap-unwrap 的情况下复制 guava 的 withFallback?
CompletableFuture<T> withFallback(CompletableFuture<T> future,
Function<Throwable, ? extends CompletableFuture<T>> fallback) {
return future.handle((response, error) -> {
if (error == null)
return CompletableFuture.completedFuture(response);
else
return fallback.apply(error);
}).thenCompose(Function.identity());
}
...
// Here's the first part of the question implemented using withFallback.
// It's a little cleaner, but it still requires wrapping as a future.
withFallback(someService.call(request), error -> {
if (error instanceof OCCException)
return CompletableFuture.completedFuture(makeDefaultResponse());
CompletableFuture<Response> errorFuture = new CompletableFuture<>();
errorFuture.completeExceptionally(error);
return errorFuture;
});
为了完整起见,如果我允许包装异常,它会是什么样子。 (我有一个单元测试来验证抛出的异常是否沿着链传播):
someService.call(request)
.exceptionally(error -> {
if (error instanceof OCCException)
return makeDefaultResponse();
else
// wrap because error is declared as a checked exception
throw new RuntimeException(error);
});
最佳答案
你要求的 Guava 风格的功能可以这样实现:
static <T> CompletableFuture<T> withFallback(CompletableFuture<T> future,
Function<Throwable, ? extends CompletableFuture<T>> fallback) {
return future.handle((response, error) -> error)
.thenCompose(error -> error!=null? fallback.apply(error): future);
}
两者兼而有之,在我们不想做任何转换的情况下,通过重用源 future 来更紧凑和节省资源。但是为了让调用者有机会在不引入另一个辅助方法的情况下执行相同的操作,更改方法并使用 BiFunction
获取源 future 作为附加参数将非常有用:
static <T> CompletableFuture<T> withFallback(CompletableFuture<T> future,
BiFunction<CompletableFuture<T>, Throwable, ? extends CompletableFuture<T>>
fallback) {
return future.handle((response, error) -> error)
.thenCompose(error -> error!=null? fallback.apply(future,error): future);
}
然后你可以像这样使用它:
withFallback(someService.call(request), (f,t) -> t instanceof OCCException?
CompletableFuture.completedFuture(makeDefaultResponse()): f)
关于java - CompletableFuture withFallback/只处理一些错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25338376/