处理失败的“未来" [英] Dealing with a Failed `Future`
问题描述
给定以下两种方法:
def f: Future[Int] = Future { 10 }
def g: Future[Int] = Future { 5 }
我想创作它们:
scala> import scala.concurrent.Future
import scala.concurrent.Future
scala> import scala.concurrent.Future._
import scala.concurrent.Future._
scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global
scala> for {
| a <- f
| b <- g
| } yield (a+b)
res2: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@34f5090e
现在,我将调用 Await.result
阻塞直到它完成.
Now, I'll call Await.result
to block until it's finished.
scala> import scala.concurrent.duration._
import scala.concurrent.duration._
正如预期的那样,我得到 15
,因为 Await.result
接受了一个 Future[Int]
并返回了一个 Int代码>.
As expected, I get 15
, since Await.result
took a Future[Int]
and returned an Int
.
scala> Await.result(res2, 5.seconds)
res6: Int = 15
为失败的 Future 定义一个 recoverFn
:
Defining a recoverFn
for a failed Future:
scala> val recoverFn: PartialFunction[Throwable, Future[Int]] =
{ case _ => Future{0} }
recoverFn: PartialFunction[Throwable,scala.concurrent.Future[Int]] = <function1>
我尝试定义一个失败的未来:
I try to define a failedFuture:
scala> def failedFuture: Future[Int] = Future { 666 }.failed.recoverWith{ recoverFn }
<console>:20: error: type mismatch;
found : scala.concurrent.Future[Any]
required: scala.concurrent.Future[Int]
def failedFuture: Future[Int] = Future { 666 }.failed.recoverWith{ recoverFn }
^
但是,我收到了上述编译时错误.
But, I get the above compile-time error.
具体来说,我该如何解决这个错误?通常,Future#recoverWith
通常是如何处理失败的 Future
的?
Specifically, how can I fix this error? Generally, is Future#recoverWith
typically how failed Future
's are handled?
推荐答案
问题在于 Future#failed
always 返回 Future[Throwable]
.其目的不是简单地使Future
失败,而是返回该Future
的失败投影.这意味着如果原始 Future
失败,它将被转换为一个 successful Future
保存异常.如果原来的 Future
成功了,那么它就失败了,并持有一个 NoSuchElementException
.您遇到的错误是因为您实际上是在使用 Future[Int]
恢复 Future[Throwable]
,它具有 Future 的最小上限[任何]
.
The problem is that Future#failed
always returns Future[Throwable]
. It's purpose is not to simply fail a Future
, but instead to return a failed projection of that Future
. This means that if the original Future
failed, it will be converted to a successful Future
that holds the exception. And if the original Future
succeeded, then it becomes failed, and holds a NoSuchElementException
. The error you are getting is because you're essentially recovering a Future[Throwable]
with a Future[Int]
, which has a least upper-bound of Future[Any]
.
如果你只是想尝试一下失败的Future
,试试这个:
If you're just trying to play with failed Future
s, try this instead:
scala> Future.failed[Int](new Exception("???")).recoverWith(recoverFn)
res4: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@6933711b
scala> res4.value.get
res5: scala.util.Try[Int] = Success(0)
recoverWith
没有任何问题.
这篇关于处理失败的“未来"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!