难以从多个不同类型的期货组成Scala Future

时间:2016-07-09 20:10:42

标签: scala future

我有两个函数:一个返回Future[Thing Or Exception],另一个返回Future[Boolean。我想要一个调用两个函数并返回Future[Thing Or Exception]的函数。如果布尔函数返回false,我想返回异常,否则返回另一个函数。

我有这样的代码但是a)我讨厌演员和b)当在“boolean gets true”路径上运行时,当我最终Await.result在我的测试代码中返回时,我得到了这个错误:{{ 1}}。

"Promise$DefaultPromise cannot be cast to org.scalatic.Or"

我也试过了,但它在成功路径上得到了相同的Promise错误

def thingFuture: Future[Thing Or Exception]
def boolFuture: Future[Boolean]

def combineFutures: Future[Thing Or Exception] = {
   val result = boolFuture.map {x =>
     x match {
      case true => thingFuture
      case false => Exception
     }
   }
   // without the cast compiler says result is of type Future[Object]
   result.asInstanceOf[Future[Thing Or Exception]]
}

有谁能告诉我如何用不同的回报类型撰写两个期货?谢谢!

2 个答案:

答案 0 :(得分:2)

在发生异常的情况下,每个未来都可以通过失败状态完成,因此您只需在"快乐路径中返回thingFuture"如果boolean为false,则抛出异常。这将返回带有基础异常的Future.failed

val result = boolFuture.flatMap {x =>
  x match {
    case true => thingFuture
    case false => throw new Exception("whatever")
  }
}

请注意flatMap而不是map。因为我们将一个未来的基本价值映射到另一个未来,通过使用简单的map,我们最终会得到Future[Future[Thing]]

另请注意,您可以返回Future.failed(throw new Exception("whatever"))而不是抛出异常,结果也是相同的 - 在这两种情况下,您都会遇到失败的未来。

编辑:我刚刚意识到Or来自scalactic,我从未使用过,但哲学仍然是一样的。你需要flatMap你的布尔未来和你的ThingOrException未来才能结束Future[ThingOrException]。如果您发现自己处于需要flatMap未来的情况,但其中一个case子句返回一个普通值(例如,如果是真实的返回Future[Thing],则在返回错误的情况下Exception )然后你可以将普通价值包装到未来。这样所有分支都返回一个未来,flatMap将正常工作。例如:

val someOtherFuture = Future(43)
val someOrdinaryValue = 44

Future(someInteger).flatMap {
  case 42 => someOtherFuture
  case _  => Future(someOrdinaryValue)
}

为了简化运行时机制的内容,您还可以编写Future.successful(someOrdinaryValue),在这种情况下不会启动后台计算。

答案 1 :(得分:1)

据我在Scalatic文档中可以看出,您可以Right Or LeftGood(Right)获取Bad(Left)的实例。

这意味着构图可能看起来像这样:

boolFuture.flatMap(b => if (b) thingFuture else Future.successful(Bad(new Exception())))

这些类型应统一为Future[Or[Thing, Exception]]