CompletableFuture withFallback /只处理一些错误 [英] CompletableFuture withFallback / handle only some errors

查看:107
本文介绍了CompletableFuture withFallback /只处理一些错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过CompletableFuture收到服务电话的回复。我想处理服务返回的一些已知异常—比如乐观并发控制冲突。

I'm receiving responses from a service call via CompletableFuture. I'd like to handle some known exceptions the service returns — such as optimistic concurrency control conflicts.

这就是我所拥有的。是否有更好的方法来执行不包装异常或使用SneakyThrows?包装异常意味着其他异常处理程序必须检查因果链,而不是仅使用 instanceof

Here's what I've got. Is there a better way to do this which does not wrap the exceptions or use SneakyThrows? Wrapping exceptions would mean other exception handlers must inspect causal chains instead of merely using 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());

同样的,有没有办法复制guava的withFallback而没有wrap-unwrap?

Along the same vein, is there a way to replicated guava's withFallback without the wrap-unwrap?

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;
});






为了完整性,这就是它的样子如果我允许要包装的例外。 (我有一个单元测试来验证抛出的异常在链中传播):


For completeness, here is what it would look like if I allowed the exceptions to be wrapped. (I've got a unit test to verify the thrown exception propagates down the chain):

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);
    });


推荐答案

您要求的番石榴风格功能可以像这个:

The guava style function you asked for could be implemented like this:

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);
}

通过重复使用案例的未来来源,更加紧凑并节省资源我们不想做任何改造。但是为了让调用者有机会在不引入另一个辅助方法的情况下执行相同操作,更改方法并使用 BiFunction 获取源代码未来将非常有用作为附加参数:

being both, more compact and saving resources by reusing the source future for the case we don’t want to do any transformations. But to give the caller the opportunity to do the same without the introduction of another helper method, it would be very useful to change the method and use a BiFunction which gets the source future as additional parameter:

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);
}

然后你就可以这样使用它:

then you can use it like this:

withFallback(someService.call(request), (f,t) -> t instanceof OCCException?
                  CompletableFuture.completedFuture(makeDefaultResponse()): f)

这篇关于CompletableFuture withFallback /只处理一些错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆