2016-07-09 21 views
2

Ich habe zwei Funktionen: eine gibt eine Future[Thing Or Exception] zurück und eine andere, die Future[Boolean zurückgibt. Ich möchte eine Funktion, die beide aufruft und Future[Thing Or Exception] zurückgibt. Wenn die boolesche Funktion false zurückgibt, möchte ich eine Ausnahme zurückgeben, andernfalls die Rückgabe der anderen Funktion.Probleme beim Zusammenstellen von Scala Future aus mehreren Futures unterschiedlicher Typen

Ich habe Code wie folgt, aber a) Ich hasse die Besetzung und b) wenn auf dem "Boolean wird wahr" Pfad ausgeführt bekomme ich diesen Fehler, wenn ich schließlich Await.result auf die Rückkehr in meinem Testcode: "Promise$DefaultPromise cannot be cast to org.scalatic.Or".

def thingFuture: Future[Thing Or Exception] 
def boolFuture: Future[Boolean] 

def combineFutures: Future[Thing Or Exception] = { 
    val result = boolFuture.map {x => 
    x match { 
     case true => thingFuture 
     case false => Exception 
    } 
    } 
    // without the cast compiler says result is of type Future[Object] 
    result.asInstanceOf[Future[Thing Or Exception]] 
} 

Ich habe dies auch versucht, aber es wird die gleichen Versprechen Fehler auf dem Erfolgsweg mir

def combineFutures: Future[Thing Or Exception] = { 
    val result = boolFuture.map {x => 
    x match { 
     case true => thingFuture.map { y => 
     y match { 
      case Good(thing) => thing 
      case Bad(exception) => exception 
     } 
     case false => Exception 
    } 
    } 
} 

Kann jemand sagen, wie mit unterschiedlichen Rückgabetypen zwei Futures zu komponieren? Vielen Dank!

Antwort

2

Jede Zukunft kann mit einem Fehlerstatus abgeschlossen werden, falls eine Ausnahme aufgetreten ist. Sie können also einfach dingFuture im "Happy Path" zurückgeben und eine Ausnahme auslösen, falls boolean falsch ist. Dies wird eine Future.failed mit der zugrunde liegenden Ausnahme zurückgeben.

val result = boolFuture.flatMap {x => 
    x match { 
    case true => thingFuture 
    case false => throw new Exception("whatever") 
    } 
} 

Notiere die flatMap statt map. Weil wir den zugrunde liegenden Wert einer Zukunft in eine andere Zukunft abbilden, würden wir mit der einfachen map mit Future[Future[Thing]] enden.

Beachten Sie auch, dass Sie anstelle einer Ausnahme auch eine Future.failed(throw new Exception("whatever")) zurückgeben könnten und das Ergebnis wäre das gleiche - in beiden Fällen erhalten Sie eine fehlgeschlagene Zukunft.

EDIT: Ich habe gerade realisiert Or kommt von Scalactic, die ich nie verwendet, aber die Philosophie bleibt die gleiche. Sie müssen Ihre boolesche Zukunft und Ihre ThingOrException Zukunft planen, um mit Future[ThingOrException] zu enden. Wenn Sie sich jemals in einer Situation befinden, in der Sie eine Zukunft flatMap machen müssen, aber eine der case-Klauseln einen gewöhnlichen Wert zurückgibt (z. B. im Falle einer echten Rückgabe Future[Thing], bei falscher Rückgabe nur Exception), können Sie den gewöhnlichen Wert umbrechen in eine Zukunft. Auf diese Weise geben alle Zweige eine Zukunft zurück und flatMap wird korrekt funktionieren. Zum Beispiel:

val someOtherFuture = Future(43) 
val someOrdinaryValue = 44 

Future(someInteger).flatMap { 
    case 42 => someOtherFuture 
    case _ => Future(someOrdinaryValue) 
} 

Um die Dinge für die Runtime-Maschinen ein wenig zu vereinfachen, können Sie auch schreiben Future.successful(someOrdinaryValue) in diesem Fall keine Hintergrund-Berechnung gestartet.

1

Soweit ich aus der Scalatic-Dokumentation ersehen kann, können Sie eine Instanz von Right Or Left entweder durch Good(Right) oder Bad(Left) erhalten.

, dass die Zusammensetzung bedeutet, kann möglicherweise wie folgt aussehen:

boolFuture.flatMap(b => if (b) thingFuture else Future.successful(Bad(new Exception()))) 

Die Typen Future[Or[Thing, Exception]]

vereinigen sollte