2015-07-02 77 views
3

考慮以下兩種方法:處理失敗的`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] = [email protected] 

現在,我會打電話給Await.result阻塞,直到它完成。

scala> import scala.concurrent.duration._ 
import scala.concurrent.duration._ 

正如預期的那樣,我得到15,因爲Await.result拿了Future[Int]和返回Int

scala> Await.result(res2, 5.seconds) 
res6: Int = 15 

定義爲recoverFn一個失敗的未來:

scala> val recoverFn: PartialFunction[Throwable, Future[Int]] = 
    { case _ => Future{0} } 
recoverFn: PartialFunction[Throwable,scala.concurrent.Future[Int]] = <function1> 

我試圖定義一個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 } 
                     ^

但是,我得到上面的編譯時錯誤。

具體來說,我該如何解決這個錯誤?一般來說,Future#recoverWith通常如何處理Future的處理失敗?

回答

7

問題是,Future#failed總是返回Future[Throwable]。它的目的是不是簡單地失敗Future,而是返回失敗的投影Future。這意味着如果原始Future失敗,它將被轉換爲成功的Future,該成員包含異常。如果原始Future成功,則它將失敗,並保留NoSuchElementException。你得到的錯誤是因爲你基本上正在用Future[Int]恢復一個Future[Throwable],它的最小上限爲Future[Any]

如果你只是想與失敗Future s到玩,試試這個:

scala> Future.failed[Int](new Exception("???")).recoverWith(recoverFn) 
res4: scala.concurrent.Future[Int] = [email protected] 

scala> res4.value.get 
res5: scala.util.Try[Int] = Success(0) 

沒有什麼錯recoverWith