【问题标题】:How to transform failed future exceptions in Scala?如何在 Scala 中转换失败的未来异常?
【发布时间】:2020-03-24 17:01:48
【问题描述】:

我一直使用recover 来转换失败期货中的异常,类似于

def selectFromDatabase(id: Long): Future[Entity] = ???

val entity = selectFromDatabase(id) recover {   
  case e: DatabaseException =>
    logger.error("Failed ...", e)
    throw new BusinessException("Failed ...", e) 
}

此代码 sn-p 将 DatabaseException 转换为 BusinessException。但是,根据问题中的评论:Scala recover or recoverWith

...一般来说,“recover”和“recoverWith”的重点不是简单地将您的异常从一种类型转换为另一种类型,而是通过以不同的方式执行任务来从失败中恢复,这样您就不再失败了。

所以显然我不应该使用recover 来转换异常。转换Future异常/失败Future的正确方法是什么?

【问题讨论】:

  • 如果您需要将一个失败转换为另一个失败,recover(或稍微更好的recoverWith { .... Future.failed(new BusinessException 以避免throw)很好。

标签: scala exception future


【解决方案1】:

由于您只是将一个异常转换为另一个异常,我认为使用recover 是可以的。当您想尝试不同的策略来解决问题时,即当您希望获得成功的结果时,请使用recoverWith。例如考虑以下使用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

【讨论】:

  • 如何使用transform 来避免抛出异常,而是返回一个新的Failed (缺点是在成功).
猜你喜欢
  • 1970-01-01
  • 2014-01-23
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多