用Java开发具有返回类型CompletableFuture
的异步方法,我们希望所得的CF正常或异常完成,具体取决于该方法成功还是失败。
但是,考虑一下例如我的方法写入了AsynchronousChannel
并在打开该通道时遇到了异常。它甚至还没有开始写作。因此,在这种情况下,我只是想让异常流向调用者。正确吗?
尽管调用方必须处理2种失败情况:1)异常,或2)被拒绝的诺言。
或者,我的方法应该捕获该异常并返回被拒绝的诺言吗?
答案 0 :(得分:2)
我认为这都是有效的设计。 Datastax实际上是从第一种方法开始设计的,该方法在借用连接时被阻塞,然后切换到完全异步模型(https://docs.datastax.com/en/developer/java-driver/3.5/upgrade_guide/#3-0-4)
作为datastax Java驱动程序的用户,我对该修复程序感到非常满意,因为它将api更改为真正的非阻塞(在您的示例中,即使打开一个通道也要付费)。
但是我不认为这里是对的...
答案 1 :(得分:2)
IMO,选项1)使得API难以使用,因为存在两种不同的错误传递路径:
程序员现在必须确保正确处理这两个路径,而不仅仅是一个。
有趣的是,C#和Javascript的行为都是始终通过返回的async
/ Task
报告Promise
函数体内抛出的异常,甚至对于在第一个await
之前抛出的异常,永远不要以异常结束async
函数调用。
即使在使用Unconfined
调度程序时,对于Kotlin的协同程序也是如此
class SynchronousExceptionExamples {
@Test
fun example() {
log.info("before launch")
val job = GlobalScope.launch(Dispatchers.Unconfined) {
log.info("before throw")
throw Exception("an-error")
}
log.info("after launch")
Thread.sleep(1000)
assertTrue(job.isCancelled)
}
}
会产生
6 [main] INFO SynchronousExceptionExamples - before launch
73 [main @coroutine#1] INFO SynchronousExceptionExamples - before throw
(...)
90 [main] INFO SynchronousExceptionExamples - after launch
请注意,main
线程中有例外,但是launch
以正确的Job
结尾。
答案 2 :(得分:1)
从呼叫者的角度来看并没有太大的区别。无论哪种情况,无论是从方法中抛出还是在可完成的将来调用get()时,都可以看到异常原因。
我可能会争辩说,可完成的未来引发的异常应该是异步计算的异常,并且不会启动该计算。