現代斯卡拉期貨是在像Either
它們包含一個成功的結果或Throwable
。如果你重新訪問scala 2.10中的這段代碼,我想你會發現情況相當愉快。
具體地,技術上scala.concurrent.Future[T]僅「是一個」 Awaitable[T]
,但_.onComplete
和Await.ready(_, timeout).value.get
都呈現其結果作爲scala.util.Try[T],這是很多像在於它要麼結果或異常Either[Throwable, T]
。
奇怪的是,_.transform
需要兩個映射函數,一個用於T => U
,一個用於Throwable => Throwable
和(除非我失去了一些東西),有沒有變壓器,未來映射爲Try[T] => Try[U]
。 Future
的.map
將允許您通過簡單地在映射函數中拋出異常來將成功轉化爲失敗,但它僅使用原始Future
的成功。它的.recover
,同樣可以將失敗轉化爲成功。如果你想成爲能夠改變對成功失敗,反之亦然,你需要建立自己的東西,這是的_.map
和_.recover
或者組合使用_.onComplete
到鏈到一個新的scala.concurrent.Promise[U]像這樣:
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
(或者你可以「皮條客」 Future
成RichFutureWithFlexibleTransform
有一個隱含的清晰度,使flexibleTransform
的一個成員函數,丟棄fut
PARAM和簡單的使用this
)
(甚至更好的是採取Try[T] => Future[U]
並調用它flexibleFlatMap
所以你可以做轉換異步的東西)
是的,使用任一,或者甚至更好,從scalaz驗證。 – 2011-04-20 09:11:24
Thx,會看看這兩個建議:) – rocksteady 2011-04-21 13:16:48