Akka(或 Scala 2.10 的标准库中)是否有方法可以将Future[A]
可能失败的 a 转换为 a Future[Either[Exception,A]]
?我知道你会写
f.map(Right(_)).recover {
case e:Exception => Left(e)
}
这似乎是一项常见的任务,我想知道我是否忽略了一些东西。我对 Scala 2.9/Akka 和 Scala 2.10 的答案很感兴趣。
Akka(或 Scala 2.10 的标准库中)是否有方法可以将Future[A]
可能失败的 a 转换为 a Future[Either[Exception,A]]
?我知道你会写
f.map(Right(_)).recover {
case e:Exception => Left(e)
}
这似乎是一项常见的任务,我想知道我是否忽略了一些东西。我对 Scala 2.9/Akka 和 Scala 2.10 的答案很感兴趣。
缺少此方法的主要原因是它实际上并没有良好的语义:静态类型Future[Either[Throwable, T]]
不能确保未来不会失败,因此类型更改通常不会给您带来太多好处。
如果你控制所有处理这些期货的代码当然是有意义的,在这种情况下,你自己添加它是微不足道的(这个名字是由于我在第一次喝咖啡之前发布的,随时用更好的东西替换):
implicit class FutureOps[T](val f: Future[T]) extends AnyVal {
def lift(implicit ec: ExecutionContext): Future[Either[Throwable,T]] = {
val p = promise[Either[Throwable,T]]()
f.onComplete {
case Success(s) => p success Right(s)
case Failure(ex) => p success Left(ex)
}
p.future
}
}
它与 Akka 2.0 期货的工作方式非常相似,因此我将这个练习留给读者。
这种转换的另一个版本(在标准 Scala 中):
f.transform(tryResult => Success(tryResult.toEither))
我不认为你会想要这样做。Akka 2.0.5 的文档显示akka.dispatch.Future
:
abstract def onComplete[U](func: (Either[Throwable, T]) ⇒ U): Future.this.type
所以 Future 可能失败的信息已经嵌入到Future[T]
. 这同样适用于 Scala 2.10 的 futures,future 可以完成为 a Try[T]
,其目的类似于Either[Exception, T]
.
//in scala.concurrent.Future:
abstract def onComplete[U]
(func: (Try[T]) ⇒ U)(implicit executor: ExecutionContext): Unit