当前位置: 首页 > 知识库问答 >
问题:

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

拓拔奇
2023-03-14

这个问题是针对Java和< code>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()并返回它返回的字符串长度:

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 */
    }
}

我的问题是:

< code>get()写得不好是因为它要求其调用方进行这种复杂的异常处理,还是这是一种常见的模式?返回< code>CompletableFuture的异步方法是否应该局限于在出错时返回出错的未来,以便它们的调用方不必编写这样的错误处理代码

共有2个答案

殳智志
2023-03-14

我认为为参数验证抛出异常是合适的,因为调用方不应该处理这些异常——非法参数是一个必须修复的bug。

但是,最好将其他异常放在返回的CompletableFuture中,以便调用者可以使用标准的CompletableFuture异常处理和链接。同样,您不会返回null未来,而是返回用null完成的未来。另请参阅已完成的CompletableFuture,但有异常。

彭阳朔
2023-03-14

简而言之,这取决于您自己的实现,但它可以改进。如果您想忽略、记录异常,或者通过不同的线程对异常做出反应,那么让调用线程处理异常可能会很有用(这里是基本示例)。然而,我看到的许多模式(见本文答案)都会让您使用try-catch块包含asyncfunction,并重新抛出一个对您的应用程序更有用的异常,由父线程处理,我认为这会更好一些。

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

 类似资料:
  • 我正试图从同步方法运行异步方法。但是我不能等待异步方法,因为我在同步方法中。我一定不理解TPL,因为这是我第一次使用它。 每个方法都需要前一个方法来完成,因为第一个方法的数据用于第二个方法。 Await运算符只能在异步方法中使用。考虑用'async'修饰符标记此方法,并将其返回类型更改为'task' 但是,如果我使用async修饰符,这将是一个异步操作。因此,如果我对的调用没有使用await运算符

  • 问题内容: 在Java中制作异步方法的同步版本的最佳方法是什么? 假设您有一个使用以下两种方法的类: 您将如何实现直到任务完成才返回的同步? 问题答案: 看看CountDownLatch。您可以使用以下类似方式模拟所需的同步行为: 您还可以通过2个参与者使用相同的行为,如下所示: 但是,如果您可以控制I 的源代码,建议您重新设计它以返回一个对象。这样,您可以在需要时轻松地在异步/同步行为之间进行切

  • 问题内容: 我正在编写一个JavaScript函数,该函数发出HTTP请求并返回对结果的承诺(但该问题同样适用于基于回调的实现)。 如果我立即知道为该函数提供的参数无效,该函数应该同步还是应该返回被拒绝的Promise(或者,如果您愿意,请使用实例调用回调)? 异步功能应 始终 以异步方式运行(特别是对于错误情况)有多重要?是否确定,如果你知道程序是不是一个合适的状态的异步操作继续进行? 例如:

  • 我有一个异步函数,我希望在失败时抛出异常。然而,似乎有一些东西阻止了这一点: 通过省略try catch块,我希望抛出一个异常,我想在函数外部处理这个异常。 我得到的实际结果有点令人困惑: 当我尝试捕获异常并抛出其他东西时,会得到相同的结果: 该函数是从try块调用的,因此看不到这如何是未处理的promise。 我正在尝试使用< code>f作为另一个函数的参数:

  • 我正在处理来自TCP套接字的大量事件(每秒10个套接字),因此我使用多线程来处理这些事件。 大多数情况下,这是正确的,但有时会出现这些事件的雪崩,有时我会得到一个ConcurrentModificationException: 12-10 14:08:42.071:E/AndreidRuntime(28135):致命例外:线程-369 12-10 14:08:42.071:E/AndreidRun