【发布时间】:2019-03-14 02:57:01
【问题描述】:
我的代码中有一个场景,我需要根据包含特定值的成功结果使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())
}
}
}
因此,在我的示例中,如果返回的 Result 的成功指标值为 false,我希望 Future 失败。正如我所提到的,我可以使用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 的建议。
【问题讨论】:
-
您希望在这两种情况下都有 new 未来?还是只在失败的情况下?
-
结果本身,在我的实际代码中,是从对演员的调用中返回的。鉴于这种结果,我不希望那个演员总是在上游传播失败。它基于通过调用添加键成功地将值存储到沙发库中。不是所有的调用代码都关心成功标志的值是否为假;这是情境性的。
-
听起来像
filter方法。 -
@om-nom-nom,如果满足我的匹配条件,我只想要一个新的未来。如果不满足匹配,则不理会现有的未来。
-
@senia,我看了
filter。那里的问题是,如果我的谓词不正确,那么生成的Future将失败,NoSuchElementException是不希望的。