【问题标题】:Future.successful(Failure(Exception)) vs just Future.failed()Future.successful(Failure(Exception)) 与只是 Future.failed()
【发布时间】:2021-04-24 07:32:54
【问题描述】:

我试图理解为什么有人会在 Scala 中使用 Future.successful(Failure(ServiceException("error"))) 而不是 Future.failed(ex) 的区别。

Future.successful(
  Failure(
    ServiceException(ErrorTypes.Validation, "Value should not be more than 30")
  )
)

【问题讨论】:

  • 和以前一样,如果你想要一个明确的错误通道,有人必须从中恢复/处理,这是有道理的。;请注意,这将返回 TryFututre。而Future.failed 用给定的异常创建了一个失败的未来,所以它是隐藏的,直到有人调用任何恢复方法。

标签: scala exception future


【解决方案1】:

很难说作者为什么会这样做,我可以猜到几个原因:

  1. 他们不知道您可以Future.fail 返回一个失败的未来。这可能会发生,因为未来的签名没有在类型中明确传达失败路径。当你看到Future[A]时,你可能会认为这个计算将来一定会成功

  2. 他们想明确说明失败。当我声明Future[Try[A]] 时,我强迫调用者处理不能直接访问A 的事实,但必须“再跳一跳”才能进入A。虽然这很微妙,但很容易写出来:

     val f: Future[Try[String]] = ???
     f.map(_.map(str => // stuff with string))
    

    但也许签名迫使调用者意识到失败的可能性。尽管Try 的表现力也很有限,因为它只能在失败路径上返回Throwable。我发现Future[Either[E, A]] 在这方面更具表现力,它允许您构建自己的故障层次结构并将其编码到类型中。

关于一元函子 IO 类型(Future[A])与双函子 IO 类型(IO[E, A],即ZIO)之间存在着一场持久的争论。我支持双函子,并且最近才使用它,我发现它非常节省时间,因为我不必深入研究实现以了解计算可能出现的失败。

【讨论】:

    【解决方案2】:

    我想在great answer by @YuvalItzchakov 的基础上补充一点,在您的问题中编写代码会使代码复杂化并使其不自然。例如,假设这个未来通常是Int,类似于:

    val succeeded = true // or any other computation
    val future = if(succeeded) {
      Future.successful(42)
    } else {
      Future.successful(Failure(new Exception("some failure text")))
    }
    

    那么首先future的类型是Future[Any],因为AnyIntFailure的最低公共根,不方便。但是,要对其进行映射,您需要执行以下操作:

    future.map {
      case i: Int =>
        println(i)
      case Failure(ex) =>
        println(ex.getMessage)
    } recover {
      case NonFatal(ex) =>
        println(s"recover ${ex.getMessage}")
    }
    

    在同一匹配案例中模式匹配 IntFailure 感觉很奇怪。如果您确实想要模式匹配 SuccessFailure,我们必须这样做:

    val succeeded = true // or any other computation
    val future = if(succeeded) {
      Future.successful(Success(42))
    } else {
      Future.successful(Failure(new Exception("some failure text")))
    }
    

    但这已经很明显是冗余了,对吧?没有人会打电话给Future.successful(Success(42))。所以我认为使用Future.failed(new Exception("some failure text"))是很清楚的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-07
      • 1970-01-01
      • 2011-07-28
      • 2018-10-27
      • 1970-01-01
      • 2020-11-02
      • 1970-01-01
      相关资源
      最近更新 更多