繁体   English   中英

从异步方法的同步部分抛出异常,返回CompletableFuture

[英]Throwing exceptions from sync portions of async methods returning CompletableFuture

此问题特定于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的异步方法是否应该将自身限制为在出现错误的情况下返回有故障的期货,从而使调用者不必编写此类错误处理代码?

简而言之,它取决于您自己的实现,但可以进行改进。 在您希望通过其他线程忽略,记录异常或对异常做出反应的情况下,让调用线程处理异常可能是有益的( 此处是基本示例)。 但是,我已经看到很多模式async 职位的答案 ),您将包含带有try-catch-blockasync函数,并为您的应用程序异常重新抛出一个更有用的方法,以由父线程处理该异常我觉得好一点。

如果您正在寻找不同的异常处理,请参阅本文以获取不同处理的示例。

我认为抛出异常以进行参数验证是适当的,因为调用者不应该处理这些异常–非法参数是必须修复的错误。

但是,最好将其他异常放入返回的CompletableFuture ,以便调用者可以使用标准的CompletableFuture异常处理和链接。 同样,你也不会返回一个null未来,但未来有完成null 另请参见CompletableFuture(已完成,带有异常)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM