我在我的代码中有一个场景,我需要根据包含特定值的成功结果使Future
失败。我可以通过flatMap
完成这项工作,但我想知道是否有更简单的方法来完成这项工作。首先,非常简单的例子:基于成功的结果失败未来
import concurrent._
case class Result(successful:Boolean)
object FutureTest {
def main(args: Array[String]) {
import ExecutionContext.Implicits._
val f = Future{Result(false)}.flatMap{ result =>
result match{
case Result(false) => Promise.failed(new Exception("The call failed!!")).future
case _ => Promise.successful(result).future
}
}
f onFailure{
case x => println(x.getMessage())
}
}
}
所以这里我举的例子,我想如果Future
返回Result
有其成功指示器的false
值失败。正如我所说,我可以使这项工作好与flatMap
,但我想消除的代码行是:
case _ => Promise.successful(result).future
这种说法似乎没有必要。我想要的行为是能够定义条件,如果它的计算结果为真,允许我返回一个与我一样不同的Future
,但如果不是这样,就把事情保持原样(有点像PartialFunction
语义。有没有办法做到这一点,我只是没有看到?我看collect
和transform
和那些似乎不成为合适人选任。
编辑
后从@Rex Kerr和@senia获得map
建议,我创建了一个PimpedFuture
,并隐式转换为代码,类似如下:
class PimpedFuture[T](f:Future[T])(implicit ex:ExecutionContext){
def failWhen(pf:PartialFunction[T,Throwable]):Future[T] = {
f map{
case x if (pf.isDefinedAt(x)) => throw pf(x)
case x => x
}
}
}
隐含
implicit def futToPimpedFut[T](fut:Future[T])(implicit ec:ExecutionContext):PimpedFuture[T] = new PimpedFuture(fut)
而新的处理代码:
val f = Future{ Result(false) } failWhen {
case Result(false) => new Exception("The call failed!!")
}
我认为这是一个少许清洁剂,同时还利用使用map
建议。
你想在这两种情况下*新*未来?或者只有在失败的情况下? –
结果本身,在我的实际代码中,是从调用返回给演员的。鉴于这种结果,我不希望该演员总是向上游传播失败。它基于通过调用添加密钥成功将值存储到couchbase中。并不是所有的调用代码都会关心成功标志的值是否为false;这是情景。 – cmbaxter
听起来像['filter'](https://github.com/scala/scala/blob/v2.10.1/src/library/scala/concurrent/Future.scala#L306)方法。 – senia