2016-10-15 10 views
1

の理解のために、は、他の行と比較して最初の行に例外がスローされたときに矛盾して動作することがわかりました。例外をスラッシュに入れたときの不一致の動作

は、次のコード例を検討:

import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.Future 
import scala.util.{Failure, Success} 

object ForComprehensionTester { 
    def main(args: Array[String]): Unit = { 
    val result: Future[String] = for { 
     x <- returnString() // Comment out this line and exception will not be captured, but propagated. 
     y <- throwException() 
    } yield y 

    result.onComplete { 
     case Success(s) => System.out.println(s"Success: $s") 
     case Failure(t) => System.out.println(s"Exception captured!") 
    } 

    Thread.sleep(2000) 
    } 

    def returnString() = Future { 
    "content" 
    } 

    def throwException(): Future[String] = throw new RuntimeException 
} 

例外で上記のコードの結果はonCompleteの機能に取り込まれ、処理されます。しかし、8行目をコメントアウトすると、代わりに例外が伝播します。

誰かが何が起こっているのか説明できますか?

答えて

1

理解のための構文はsugarです。あなたがmapの観点から考えるとflatMap

val result: Future[String] = for { 
     x <- returnString() // Comment out this line and exception will not be captured, but propagated. 
     y <- throwException() 
    } yield y 

上記のコードはここ

returnString.flatMap { str => 
    throwException() 
} 

に変換する標準ライブラリからflatMap実装されている場合は、動作を理解することができます。 flatMapは、内部にスローされた例外を処理します。

def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = { 
    import impl.Promise.DefaultPromise 
    val p = new DefaultPromise[S]() 
    onComplete { 
     case f: Failure[_] => p complete f.asInstanceOf[Failure[S]] 
     case Success(v) => try f(v) match { 
     // If possible, link DefaultPromises to avoid space leaks 
     case dp: DefaultPromise[_] => dp.asInstanceOf[DefaultPromise[S]].linkRootOf(p) 
     case fut => fut.onComplete(p.complete)(internalExecutor) 
     } catch { case NonFatal(t) => p failure t } 
    } 
    p.future 
    } 

あなたが理解するためにreturnStringをコメントアウトthrowExceptionによってスローされ、その例外が関数で処理されていない

throwException() 

注意となります。

はありがとう例外

def throwException(): Future[String] = Future { throw new RuntimeException } 
+0

をキャプチャするには、以下のようなthrowExceptionを宣言します。すべて今クリアする。 – Obszczymucha

関連する問題