gpt4 book ai didi

Scala - 链接 future 尝试区 block ?

转载 作者:行者123 更新时间:2023-12-02 21:04:33 24 4
gpt4 key购买 nike

是否可以链接 scala.util.Try 和 scala.concurrent.Future?它们都有效地提供了相同的单子(monad)接口(interface),但尝试链接它们会导致编译错误。

例如。鉴于下面的两个签名

def someFuture:Future[String] = ???
def processResult(value:String):Try[String] = ???

是否可以执行以下操作?

val result = for( a <- someFuture; b <- processResult( a ) ) yield b;
result.map { /* Success Block */ } recover { /* Failure Block */ }

这显然会导致编译错误,因为 Future 和 Try 无法一起进行 flatMapp。

然而,能够链接它们将是一个很好的功能 - 这可能吗?或者我需要将它们组合成 Future[Try[String]] 吗?

(特别是,我对使用单个“恢复” block 来捕获 future try 中的异常感兴趣)。

最佳答案

当遇到这样的问题时,您想要在 for 理解中使用不同的类型,一种解决方案可以是尝试选择其中一种类型并将另一种类型映射到它。对于您的情况,考虑到 future 的独特属性(异步),我会选择 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)
}
}

现在,如果您发现这是一种非常常见的情况,并且您不喜欢不断添加显式转换,我想您可以将 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 */ }

请记住,调用 Future.successFuture.failed 会对范围内的任何 ExecutionContext 产生影响,因为它将提交另一个幕后任务。

编辑

正如 Viktor 在评论中指出的那样,如果您只使用 Future.fromTry,将 Try 转换为 Future 的过程会更容易> 就像下面更新的示例一样:

val result = for{
a <- someFuture
b <- Future.fromTry(processResult(a))
} yield b
result.map { /* Success Block */ } recover { /* Failure Block */ }

与使用隐式操作或滚动自己的转换逻辑相比,这可能是您最好的选择。

关于Scala - 链接 future 尝试区 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17907772/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com