Jam*_*ies 22 scala exception-handling future
是否可以链接scala.util.Try和scala.concurrent.Future?它们都有效地提供相同的monadic接口,但是尝试链接它们会导致编译错误.
例如.鉴于下面的两个签名
def someFuture:Future[String] = ???
def processResult(value:String):Try[String] = ???
Run Code Online (Sandbox Code Playgroud)
可以做以下的事情吗?
val result = for( a <- someFuture; b <- processResult( a ) ) yield b;
result.map { /* Success Block */ } recover { /* Failure Block */ }
Run Code Online (Sandbox Code Playgroud)
这显然会导致编译错误,因为Future和Try无法一起进行flatMapp.
然而,能够链接它们是一个很好的功能 - 这是否可能?或者我是否需要将它们组合成一个Future [Try [String]]?
(特别是,我有兴趣使用单个'recover'块来捕获未来或 try中的异常).
cmb*_*ter 27
当遇到这样的问题时,你想要在理解中使用不同的类型,一种解决方案可以尝试选择其中一种类型并将另一种类型映射到它.根据您的情况,鉴于期货的独特属性(异步),我会选择Future
最低公分母并将其映射Try
到Future
.你可以这样做:
val result = for{
a <- someFuture
b <- tryToFuture(processResult(a))
} yield b
result.map { /* Success Block */ } recover { /* Failure Block */ }
def tryToFuture[T](t:Try[T]):Future[T] = {
t match{
case Success(s) => Future.successful(s)
case Failure(ex) => Future.failed(ex)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您发现这是一种非常常见的情况,并且您不喜欢不断添加显式转换,我想您可以将tryToFuture
方法定义为隐含在某个帮助程序对象上,并将其导入需要的地方,如下所示:
object FutureHelpers{
implicit def tryToFuture[T](t:Try[T]):Future[T] = {
t match{
case Success(s) => Future.successful(s)
case Failure(ex) => Future.failed(ex)
}
}
}
import FutureHelpers._
val result = for{
a <- someFuture
b <- processResult(a)
} yield b
result.map { /* Success Block */ } recover { /* Failure Block */ }
Run Code Online (Sandbox Code Playgroud)
只记得调用Future.success
并对范围内的Future.failed
任何ExecutionContext
内容产生影响,因为它会在引擎盖下提交另一个任务.
编辑
正如Viktor在评论中指出的那样,如果你只是在下面的更新示例中使用,那么将a转换Try
为a的Future
过程就更容易Future.fromTry
了:
val result = for{
a <- someFuture
b <- Future.fromTry(processResult(a))
} yield b
result.map { /* Success Block */ } recover { /* Failure Block */ }
Run Code Online (Sandbox Code Playgroud)
这可能是您最好的选择,而不是使用implicits或滚动您自己的转换逻辑.