处理失败的“未来" [英] Dealing with a Failed `Future`

查看:40
本文介绍了处理失败的“未来"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下两种方法:

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 Futures, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆