現代の scala の先物は、Either
成功した結果またはThrowable
. scala 2.10 でこのコードを再度参照すると、状況が非常に快適であることがわかると思います。
具体的には、scala.concurrent.Future[T]技術的には "is-a" のみですAwaitable[T]
が_.onComplete
、Await.ready(_, timeout).value.get
どちらもその結果をscala.util.Try[T]Either[Throwable, T]
として提示します。これは、結果または例外のいずれかであるという点でよく似ています。
奇妙なことに、_.transform
2 つのマッピング関数を使用T => U
しThrowable => Throwable
ますTry[T] => Try[U]
。Future
は、マッピング関数で例外をスローするだけで成功を失敗に変えることができますが、元の.map
の成功に対してのみそれを使用しFuture
ます。その.recover
, 同様に失敗を成功に変えることができます. 成功を失敗に、またはその逆に変更できるようにしたい場合は、次のように新しいscala.concurrent.Promise[U]にチェーンするために使用するか_.map
、_.recover
または組み合わせたものを自分で作成する必要があります。_.onComplete
import scala.util.{Try, Success, Failure}
import scala.concurrent.{Future, Promise}
import scala.concurrent.ExecutionContext
def flexibleTransform[T,U](fut: Future[T])(f: Try[T] => Try[U])(implicit ec: ExecutionContext): Future[U] = {
val p = Promise[U]
fut.onComplete { res =>
val transformed = f(res)
p.complete(transformed)
}
p.future
}
次のように使用されます。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration.Duration.Inf
def doIt() {
val a: Future[Integer] = Future {
val r = scala.util.Random.nextInt
if (r % 2 == 0) {
throw new Exception("we don't like even numbers")
} else if (r % 3 == 0) {
throw new Exception("we don't like multiples of three")
} else {
r
}
}
val b: Future[String] = flexibleTransform(a) {
case Success(i) =>
if (i < 0) {
// turn negative successes into failures
Failure(new Exception("we don't like negative numbers"))
} else {
Success(i.toString)
}
case Failure(ex) =>
if (ex.getMessage.contains("three")) {
// nevermind about multiples of three being a problem; just make them all a word.
Success("three")
} else {
Failure(ex)
}
}
val msg = try {
"success: " + Await.result(b, Inf)
} catch {
case t: Throwable =>
"failure: " + t
}
println(msg)
}
for { _ <- 1 to 10 } doIt()
次のようなものが得られます。
failure: java.lang.Exception: we don't like even numbers
failure: java.lang.Exception: we don't like negative numbers
failure: java.lang.Exception: we don't like negative numbers
success: three
success: 1756800103
failure: java.lang.Exception: we don't like even numbers
success: 1869926843
success: three
failure: java.lang.Exception: we don't like even numbers
success: three
(または、暗黙的な def を使用して a に「pimp」Future
し、そのメンバー関数を作成して、パラメーターをドロップし、単に を使用することもできます)RichFutureWithFlexibleTransform
flexibleTransform
fut
this
(変換で非同期処理を実行できるように、それを取得Try[T] => Future[U]
して呼び出すことをお勧めします)flexibleFlatMap