2013-08-15 7 views
28

mapExceptionがスカラーで失敗したFutureの最もクリーンな方法は何ですか?失敗した未来の例外のマップ

は、私が持っていると言う:

import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 

val f = Future { 
    if(math.random < 0.5) 1 else throw new Exception("Oh no") 
} 

未来1に成功した場合、私はそれが失敗したが場合、私は別のExceptionExceptionを変更したい、それを維持したいと思います。

私が思い付くことができる最高の変換である、しかしそれは、成功事例のために不要な機能を作るために私を必要とします。

val f2 = f.transform(s => s, cause => new Exception("Something went wrong", cause)) 

にはmapFailure(PartialFunction[Throwable,Throwable])はありません何らかの理由はありますか?

+7

変換は正しい方法です。 s => s関数を作成する必要はありません。単に '' identity''を渡すだけです。 –

+0

乾杯。私は 'identity'関数について知らなかった。それが便利になる場所が増えてくるだろうと確信しています。 – theon

答えて

26

あなたが行うことができますScalaの2.12以来
f recover { case cause => throw new Exception("Something went wrong", cause) } 

f transform { 
    case s @ Success(_) => s 
    case Failure(cause) => Failure(new Exception("Something went wrong", cause)) 
} 

または

f transform { _.transform(Success(_), cause => Failure(new Exception("Something went wrong", cause)))} 
+1

これは非常に明確な構文ですが、 'Throwable'を' Throwable'にマッピングするのではなく、新しい例外を 'スローする '必要があります。それだけのコンビネータはありますか? – owensmartin

+0

@owensmartin私の更新されたレスポンスを参照してください。 :) –

13

のようにあなたはrecoverWithを試みることができる:もあり

f recoverWith{ 
    case ex:Exception => Future.failed(new Exception("foo", ex)) 
} 
+0

Future.failedはExeecutionContextで評価されません。http://www.scala-lang.org/api/current/#scala.concurrent.Future$「失敗しました」を参照してください。 –

+0

@ViktorKlang、私は混乱しなければなりません。私は 'impl.KeptPromise'クラスの' onComplete'メソッドを見てこの前提を作っていました。そこには 'val preparedEC = executor.prepare;という2つの行があります。 (新しいCallbackRunnable(preparedEC、func))。executeWithValue(completedAs) 'を呼び出します。私は、たとえ何らかの理由で依然としてエグゼクターを襲​​っているという明白な価値を与えていたとしても、このことを暗示していました。それはいつも私には奇妙に思えました。私はそれを誤読していたので、実際にはそうだと思います。ヘッドアップをありがとう。 – cmbaxter

+0

答えをありがとう。 'recover' /' recoverWith'を使った私の唯一の躊躇は、私がそれを見るとすぐに、成功の結果で失敗から回復することを意図していると思います。多分それは私だけです。それでも、彼らは良い選択肢です、ありがとう! – theon

関連する問題