一个描述我的问题的简单代码示例:
import scala.util._ import scala.concurrent._ import scala.concurrent.duration._ import ExecutionContext.Implicits.global class LoserException(msg: String,dice: Int) extends Exception(msg) { def diceRoll: Int = dice } def aPlayThatMayFail: Future[Int] = { Thread.sleep(1000) //throwing a dice takes some time... //throw a dice: (1 + Random.nextInt(6)) match { case 6 => Future.successful(6) //I win! case i: Int => Future.Failed(new LoserException("I did not get 6...",i)) } } def win(prefix: String): String = { val futureGameLog = aPlayThatMayFail futureGameLog.onComplete(t => t match { case Success(diceRoll) => "%s,and finally,I won! I rolled %d !!!".format(prefix,diceRoll) case Failure(e) => e match { case ex: LoserException => win("%s,and then i got %d".format(prefix,ex.diceRoll)) case _: Throwable => "%s,and then somebody cheated!!!".format(prefix) } }) "I want to do something like futureGameLog.waitForRecursiveResult,using Await.result or something like that..." } win("I started playing the dice")
这个简单的例子说明了我想做的事情.基本上,如果用文字表达,我想等待一些计算的结果,当我对先前的成功或失败的成功构成不同的行动.
那你怎么实现win方法呢?
我的“真实世界”问题,如果它有任何区别,就是使用dispatch进行异步http调用,我想在前一个调用结束时继续进行http调用,但是前一个http调用成功与否的操作不同.
解决方法
您可以通过递归调用恢复失败的未来:
def foo(x: Int) = x match { case 10 => Future.successful(x) case _ => Future.Failed[Int](new Exception) } def bar(x: Int): Future[Int] = { foo(x) recoverWith { case _ => bar(x+1) } } scala> bar(0) res0: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@64d6601 scala> res0.value res1: Option[scala.util.Try[Int]] = Some(Success(10))
recoverWith采用PartialFunction [Throwable,scala.concurrent.Future [A]]并返回Future [A].你应该小心,因为它会在这里进行大量的递归调用时使用相当多的内存.