如何在Scala中转换失败的未来异常? [英] How to transform failed future exceptions in Scala?
问题描述
我一直使用 recover
来转换失败的期货中的异常,类似于
I have always used recover
to transform exceptions in failed futures similar to
def selectFromDatabase(id: Long): Future[Entity] = ???
val entity = selectFromDatabase(id) recover {
case e: DatabaseException =>
logger.error("Failed ...", e)
throw new BusinessException("Failed ...", e)
}
此代码段将 DatabaseException
转换为 BusinessException
。但是,从对问题的评论中: Scala恢复或recoverWith
This code snippet transforms a DatabaseException
into a BusinessException
. However, from a comment in the question: Scala recover or recoverWith
...一般来说, recover和 recoverWith的意义不是简单地将异常从一种类型转换为另一种类型,而是通过从故障中恢复
... generally speaking the point of "recover" and "recoverWith" is not to simply transform your exceptions from one type to another, but to recover from the failure by performing the task in a different way so that you no longer have a failure.
因此,显然我不应该使用恢复
来转换异常。转换未来
异常/失败的未来
的正确方法是什么?
So apparently I am not supposed to use recover
to transform exceptions. What is the correct way to transform Future
exceptions / failed Future
?
推荐答案
由于您只是将一个异常转换为另一个异常,我认为使用 recover
是可以的。当您想尝试解决问题的其他策略时,即希望返回成功的结果时,请使用 recoverWith
。例如,考虑以下 recoverWith
Since you are simply transforming an exception to another exception, I think using recover
is ok. Use recoverWith
when you want to try a different strategy for solving the problem, that is, when you hope to get a successful result back. For example consider the following use of recoverWith
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object futureRecoverWith extends App {
case class Entity(id: Int, name: String)
def selectFromDatabaseById(id: Int): Future[Entity] = Future(throw new RuntimeException("Boom"))
def selectFromDatabaseByName(name: String): Future[Entity] = Future(Entity(42, "picard"))
val entity =
selectFromDatabaseById(42) recoverWith {
case error =>
println("Failed to get Entity by ID. Trying by name...")
selectFromDatabaseByName("picard")
}
entity.map(println)
}
输出
Failed to get Entity by ID. Trying by name...
Entity(42,picard)
请注意我们如何尝试首先通过 id
获取实体,然后失败,我们尝试通过 name
命名。
Note how we attempted to first get the entity by id
, and then failing that, we attempted by name
.
这篇关于如何在Scala中转换失败的未来异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!