2016-03-23 15 views
1

Was ist der beste Weg istScala, führen Karte von Futures

Map[String, Future[A]] 

zu

Map[String, A] 

zu gehen, wo A das Ergebnis der entsprechenden Zukunft der Ausführung ist?

Dies wird nicht kompilieren:

val results = for { 
    (key, future) <- myMap 
    result <- future 
} yield (key, result) 

, da ich nicht Futures und Iterables im gleichen für das Verständnis mischen.

+2

Sie erkennen, dass Sie von "Map [String, Future [A]]" zu »Map [String, A]" wechseln müssen. Ist das in Ihrem Fall in Ordnung? Ansonsten denke ich, was du wirklich willst, geht von 'Map [String, Future [A]]' zu 'Future [Map [String, A]]' ' –

+0

@ RégisJean-Gilles gute Bemerkung. Diese [Antwort] (http://stackoverflow.com/questions/17479160/how-to-convert-mapa-futureb-to-futuremapa-b) enthält Hinweise, um das auch zu tun. – ticofab

Antwort

2

Wenn Sie es in eine Seq[Future[(String,A)]] konvertieren, können Sie dann Future.fold verwenden, um es einen einzigen Future[Map[...]] zurück:

def transform[A](m: Map[String, Future[A]]): Future[Map[String, A]] = { 
    val seq: Seq[Future[(String, A)]] = m.toSeq.map { case (key, f) => 
    f.map(i => key -> i) 
    } 

    Future.fold(seq)(Map.empty[String, A])(_ + _) 
} 

dann die einzige Zukunft als normal einlösen.

0

So etwas wie dies vielleicht:

map.mapValues { Await.result(_, 5 seconds) } 
+0

Ihre zweite Alternative wird nicht kompiliert. –

+0

In der Tat. Entfernen Sie es. – Dima

-1

Dima gab bereits eine Antwort mit Await. Es wird jedoch eine Ausnahme auslösen, wenn die Zukunft fehlschlägt.

Sie können die Typen weiter einbetten als Try und dann eine .collect, um nur für die erfolgreichen Futures zu filtern (überprüfen Sie die offizielle API dafür).

import scala.util.{ Try, Success } 

val results = myMap 
    .map { 
     case (key, value) => key => Try(Await.result(value, 5.seconds)) 
    } 
    .collect { 
     case (key, Success(value)) => key -> value 
    } 

Mit dem obigen Aufruf verwerfen Sie automatisch fehlgeschlagene Futures und sammeln nur erfolgreiche.

+0

Dies funktioniert nicht: Die Werte in der Karte haben den Typ 'Future', der nicht mit' Success' kompatibel ist. Die Sache ist, du musst blockieren und irgendwo warten, um von "Zukunft" zu dem tatsächlichen ("gegenwärtigen") Ergebnis zu gelangen. – Dima

+0

Aha, tatsächlich. Ich denke ich mische es diesmal mit "Try". Ich habe meine Antwort bearbeitet. 'collect' funktioniert nur, nachdem Sie das Ergebnis irgendwo abgerufen und in ein tatsächliches' Try' umgewandelt haben. – bow