Future.successful(Failure(Exception)) 与只是 Future.failed()

Posted

技术标签:

【中文标题】Future.successful(Failure(Exception)) 与只是 Future.failed()【英文标题】:Future.successful(Failure(Exception)) vs just 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 用给定的异常创建了一个失败的未来,所以它是隐藏的,直到有人调用任何恢复方法。 【参考方案1】:

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

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

    他们想明确说明失败。当我声明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"))是很清楚的。

【讨论】:

以上是关于Future.successful(Failure(Exception)) 与只是 Future.failed()的主要内容,如果未能解决你的问题,请参考以下文章

Compilation failure: Compilation failure:

Temporary failure resolving 'security.debian.org'

构建步骤“发布性能测试结果报告”将构建结果更改为 FAILURE Finished: FAILURE

Android Unknown failure (Failure - not installed for 0)

debian ssh su su: Authentication failure

Received fatal alert: handshake_failure排查过程