scala 规划成功和失败的未来
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23043679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Map a Future for both Success and Failure
提问by monkHyman
I have a Future[T] and I want to map the result, on both success and failure.
我有一个 Future[T],我想将结果映射到成功和失败上。
Eg, something like
例如,像
val future = ... // Future[T]
val mapped = future.mapAll {
case Success(a) => "OK"
case Failure(e) => "KO"
}
If I use mapor flatmap, it will only map successes futures. If I use recover, it will only map failed futures. onCompleteexecutes a callback but does not return a modified future. Transformwill work, but takes 2 functions rather than a partial function, so is a bit uglier.
如果我使用mapor flatmap,它只会映射成功的期货。如果我使用recover,它只会映射失败的期货。onComplete执行回调但不返回修改后的未来。Transform会工作,但需要 2 个函数而不是部分函数,所以有点难看。
I know I could make a new Promise, and complete that with onCompleteor onSuccess/onFailure, but I was hoping there was something I was missing that would allow me to do the above with a single PF.
我知道我可以制作一个新的Promise,并用onCompleteor onSuccess/完成它onFailure,但我希望有一些我遗漏的东西可以让我用单个 PF 完成上述操作。
回答by espenhw
Edit 2017-09-18: As of Scala 2.12, there is a transformmethod that takes a Try[T] => Try[S]. So you can write
编辑 2017-09-18:从 Scala 2.12 开始,有一种transform方法可以使用Try[T] => Try[S]. 所以你可以写
val future = ... // Future[T]
val mapped = future.transform {
case Success(_) => Success("OK")
case Failure(_) => Success("KO")
}
For 2.11.x, the below still applies:
对于 2.11.x,以下仍然适用:
AFAIK, you can't do this directly with a single PF. And transformtransforms Throwable => Throwable, so that won't help you either. The closest you can get out of the box:
AFAIK,您不能直接使用单个 PF 执行此操作。并transform转换 Throwable => Throwable,所以这也无济于事。您可以开箱即用的最接近的:
val mapped: Future[String] = future.map(_ => "OK").recover{case _ => "KO"}
That said, implementing your mapAll is trivial:
也就是说,实现你的 mapAll 是微不足道的:
implicit class RichFuture[T](f: Future[T]) {
def mapAll[U](pf: PartialFunction[Try[T], U]): Future[U] = {
val p = Promise[U]()
f.onComplete(r => p.complete(Try(pf(r))))
p.future
}
}
回答by nmat
Since Scala 2.12you can use transformto map both cases:
从Scala 2.12 开始,您可以使用transform映射两种情况:
future.transform {
case Success(_) => Try("OK")
case Failure(_) => Try("KO")
}
You also have transformWithif you prefer to use a Futureinstead of a Try. Check the documentationfor details.
transformWith如果您更喜欢使用 aFuture而不是 a ,您也可以使用Try。查看文档了解详细信息。
回答by paradigmatic
In a first step, you could do something like:
第一步,您可以执行以下操作:
import scala.util.{Try,Success,Failure}
val g = future.map( Success(_):Try[T] ).recover{
case t => Failure(t)
}.map {
case Success(s) => ...
case Failure(t) => ...
}
where Tis the type of the future result. Then you can use an implicit conversion to add this structure the Futuretrait as a new method:
哪里T是未来结果的类型。然后您可以使用隐式转换将此结构添加到Futuretrait 作为新方法:
implicit class MyRichFuture[T]( fut: Future[T] ) {
def mapAll[U]( f: PartialFunction[Try[T],U] )( implicit ec: ExecutionContext ): Future[U] =
fut.map( Success(_):Try[T] ).recover{
case t => Failure(t)
}.map( f )
}
which implements the syntax your are looking for:
它实现了您正在寻找的语法:
val future = Future{ 2 / 0 }
future.mapAll {
case Success(i) => i + 0.5
case Failure(_) => 0.0
}
回答by sungiant
Both map and flatMap variants:
map 和 flatMap 变体:
implicit class FutureExtensions[T](f: Future[T]) {
def mapAll[Target](m: Try[T] => Target)(implicit ec: ExecutionContext): Future[Target] = {
val p = Promise[Target]()
f.onComplete { r => p success m(r) }(ec)
promise.future
}
def flatMapAll[Target](m: Try[T] => Future[Target])(implicit ec: ExecutionContext): Future[Target] = {
val promise = Promise[Target]()
f.onComplete { r => m(r).onComplete { z => promise complete z }(ec) }(ec)
promise.future
}
}

