在 Java 中开发一个具有 CompletableFuture
返回类型的异步方法,我们希望生成的 CF 正常或异常完成,具体取决于该方法是成功还是失败。
但是,考虑例如我的方法写入 AsynchronousChannel
并在打开该 channel 时遇到异常。它甚至还没有开始写作。所以,在这种情况下,我倾向于让异常流向调用者。对吗?
尽管调用者必须处理 2 种失败情况:1) 异常,或 2) 拒绝 promise 。
或者,我的方法是否应该捕获该异常并返回一个被拒绝的 promise ?
最佳答案
IMO,选项 1) 使 API 更难使用,因为将有两种不同的通信错误路径:
- “同步”异常,方法在抛出异常时结束。
- “异步”异常,其中方法返回一个 CF,它以异常完成。请注意,不可能避免这种情况,因为总是会出现只有在异步路径启动后才发现错误的情况(例如超时)。
程序员现在必须确保正确处理这两条路径,而不是只处理一条。
同样有趣的是,C# 和 Javascript 的行为总是通过返回的 Task
报告在 async
函数体内抛出的异常/Promise
,即使是在第一个 await
之前抛出的异常,也永远不会以异常结束 async
函数调用。
对于 Kotlin 的协程也是如此,即使在使用 Unconfined
调度程序时也是如此
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
结束。
关于java - 异步方法抛出异常是否合理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54221665/