2017-04-18 2 views
0

Ich habe eine Methode, die Future [Try [Option [Int]]] zurückgibt. Ich möchte den Wert von Int für weitere Berechnungen extrahieren. Irgendeine Idee, wie man es verarbeitet?Prozess Zukunft [Try [Option]] in Scala

+0

versuchen zu verstehen, warum Sie eine Zukunft haben [Versuchen [Option [Int]]]. Wenn Sie sowohl Future a Try als auch Option auswählen, können Sie versuchen, Ihr Ergebnis, das aus einer Methodenkomposition in einer einzigen Zukunft stammt, zuzuordnen. –

+0

Ich stimme @FabioFumarola zu. Es ist sehr bedauerlich, mit dieser Art von Typ umgehen zu müssen. – mfirry

+1

Die richtige Antwort hängt weitgehend davon ab, wie Sie die Fehlerfälle für Future, Try und None behandeln wollen. Bitte fügen Sie weitere Details dazu hinzu. – nmat

Antwort

1

Gerade map die Zukunft und Nutzung Match Fall die verschiedenen Fälle zu behandeln:

val result: Future[Try[Option[Int]]] = ??? 
result.map { 
    case Success(Some(r)) => 
    println(s"Success. Result: $r") 
    //Further computation here 

    case Success(None) => //Success with None 
    case Failure(ex) => //Failed Try 
} 
1

Converting Future[Try[Option[Int]]] zu Future[Int]

Ein hacky Weg ist, die ungünstigen Ergebnisse in fehlgeschlagen Zukunft zu konvertieren und flatMapping über .

Konvertieren Sie Versuche fehlgeschlagen in zukünftige Fehler unter Beibehaltung der Informationen, dass die Ausnahme von Try stammte, und konvertieren Sie keine zu NoneFound-Ausnahme.

val f: Future[Try[Option[Int]]] = ??? 

case class TryException(ex: Throwable) extends Exception(ex.getMessage) 
case object NoneFound extends Exception("None found") 

val result: Future[Int] = f.flatMap { 
    case Success(Some(value)) => Future.successful(value) 
    case Success(None) => Future.failed(NoneFound) 
    case Failure(th) => Future.failed(TryException(th)) 
} 

result.map { extractedValue => 
    processTheExtractedValue(extractedValue) 
}.recover { 
    case NoneFound => "None case" 
    case TryException(th) => "try failures" 
    case th => "future failures" 
} 

Jetzt wissen Sie in jedem Fall, woher die Ausnahme stammt. Im Falle einer NoneFound-Ausnahme wissen Sie, dass Future und Try erfolgreich sind, aber die Option ist keine. Auf diese Weise gehen Informationen nicht verloren und die verschachtelte Struktur wird auf Future[Int] reduziert.

Jetzt Ergebnis wäre Future[Int]. Verwenden Sie einfach map, flatMap, recover und recoverWith, um weitere Aktionen zu erstellen.

2
future.map(_.map(_.map(i => doSomethingWith(i)))) 
0

Wenn Sie cats verwenden Sie können Spaß machen (für bestimmte Definitionen Spaß) Dinge wie:

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

import cats.Functor 
import cats.instances.option._ 
import cats.implicits._ 

val x = Future { Try { Some(1) } } // your type 

Functor[Future].compose[Try].compose[Option].map(x)(_ + 2) 

Dies wird vorgeschlagen, nur wenn Sie mit Katzen oder scalaz bereits vertraut sind. Ansonsten ist es toll, mit einer der anderen gültigen Antworten hier zu gehen (ich mag besonders die Map-Map-Map).

0

Wenn Sie wirklich besorgt über die Extraktion sehen Sie dies, sonst gehen Sie durch die Antwort von @pamu, um zu sehen, wie Sie Ihre Zukunft tatsächlich verwenden.

Angenommen, Ihr zukünftiger Wert ist result.

Await.ready(result, 10.seconds).value.get.map { i => i.get}.get

Offensichtlich wird nicht durch Ihren Ausfall und keine Fälle erhalten und Ausnahmen auslösen würde und Await wird nicht empfohlen.

Also, wenn Sie Ausfall und keinen Fall behandeln wollen ->

val extractedValue = Await.ready(f, 10.seconds).value.get match { 
case Success(i) => i match { 
    case Some(value) => value 
    case None => println("Handling None here") 
} 
case Failure(i) => println("Handling Failure here") 
}