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")
)
)
【问题讨论】:
和以前一样,如果你想要一个明确的错误通道,有人必须从中恢复/处理,这是有道理的。;请注意,这将返回 Try 的 Fututre。而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]
,因为Any
是Int
和Failure
的最低公共根,不方便。但是,要对其进行映射,您需要执行以下操作:
future.map
case i: Int =>
println(i)
case Failure(ex) =>
println(ex.getMessage)
recover
case NonFatal(ex) =>
println(s"recover $ex.getMessage")
在同一匹配案例中模式匹配 Int
和 Failure
感觉很奇怪。如果您确实想要模式匹配 Success
和 Failure
,我们必须这样做:
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)