当前位置: 首页 > 知识库问答 >
问题:

Scala - Chaining Futures试块?

王棋
2023-03-14

是否有可能将 scala.util.Try 和 scala.concurrent.Future 链接起来?它们都有效地提供了相同的一元接口,但尝试链接它们会导致编译错误。

例如。给定以下两个签名

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不能被平面映射在一起。

然而,能够链接它们将是一个很好的功能 - 这有可能吗?还是我需要将它们组合成一个未来[尝试[字符串]]?

(特别是,我感兴趣的是有一个单独的‘recover’块来捕获将来或将来的异常)。

共有3个答案

南宫松
2023-03-14

也许这个问题由来已久,但目前您可以:

  implicit def tryToFuture[T](t:Try[T]):Future[T] = Promise.fromTry(t).future
卜阳
2023-03-14

怎么样

val result = for( a <- someFuture) yield for( b <- processResult( a ) ) yield b;

虽然看起来不整齐。

刘元青
2023-03-14

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

请记住,调用< code>Future.success和< code>Future.failed会对< code>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尝试,包括了Scala尝试的使用技巧和注意事项,需要的朋友参考一下 示例 使用尝试map,getOrElse并且flatMap: Try与模式匹配一起使用:            

  • 如何在Scala中调试代码?

  • 我使用IntelliJ的SBT插件,并创建了一个具有以下构建设置的scala项目:build.scala: 任何想法都是高度赞赏的。

  • 我有一个scala测试类,但是当我试图使用Maven目标'test'运行时,测试并没有运行。我收到Maven消息“There are no tests to run”。即使测试位于scala测试类中。我需要添加额外的配置吗? 以下是我的软件包设置: 下面是针对pom文件运行时Maven“测试”目标的输出: [INFO]----------------------生成成功[INFO]--------

  • 我能够在Scala代码上运行调试器,但不能再用IntelJ IDE Community Edition 2020.1.1(2020年4月)... 对于Scala-Play应用程序,它过去是直接的(只需启动sbt控制台,然后按下“绿色小bug按钮”,我想它类似于wood attach remote process下的“attach process” 现在我得到: 运行“调试sbt shell”时出错