2014-11-12 13 views
5

Ich habe ein paar Futures. campaignFuture gibt eine List [BigInt] zurück und ich möchte die zweite future profileFuture für jeden der Werte in der Liste aufrufen können, die von der ersten zurückgegeben wurden. Die zweite Zukunft kann nur aufgerufen werden, wenn die erste abgeschlossen ist. Wie erreiche ich das in Scala?Scala Nested Futures

campaignFuture(1923).flatMap?? (May be?) 

def campaignFuture(advertiserId: Int): Future[List[BigInt]] = Future { 
    val campaignHttpResponse = getCampaigns(advertiserId.intValue()) 
    parseProfileIds(campaignHttpResponse.entity.asString) 
} 

def profileFuture(profileId: Int): Future[List[String]] = Future { 
    val profileHttpResponse = getProfiles(profileId.intValue()) 
    parseSegmentNames(profileHttpResponse.entity.asString) 
}  

Antwort

3

A zum Verständnis ist hier nicht anwendbar, da wir eine Mischung aus List und Future haben. So sind Ihre Freunde Karte und flatMap:

Zukunfts Ergebnis

das Ergebnis aller Futures auf einmal reagieren
import scala.concurrent.{Future, Promise, Await} 
    import scala.concurrent.duration.Duration 
    import scala.concurrent.ExecutionContext.Implicits.global 

    def campaignFuture(advertiserId: Int): Future[List[BigInt]] = Future { 
    List(1, 2, 3) 
    } 
    def profileFuture(profileId: Int): Future[List[String]] = { 
    // delayed Future 
    val p = Promise[List[String]] 
    Future { 
     val delay: Int = (math.random * 5).toInt 
     Thread.sleep(delay * 1000) 
     p.success(List(s"profile-for:$profileId", s"delayed:$delay sec")) 
    } 
    p.future 
    } 



    // Future[List[Future[List[String]]] 
    val listOfProfileFuturesFuture = campaignFuture(1).map { campaign => 
    campaign.map(id => profileFuture(id.toInt)) 
    } 

    // React on Futures which are done 
    listOfProfileFuturesFuture foreach { campaignFutureRes => 
    campaignFutureRes.foreach { profileFutureRes => 
     profileFutureRes.foreach(profileListEntry => println(s"${new Date} done: $profileListEntry")) 
    } 
    } 


    // !!ONLY FOR TESTING PURPOSE - THIS CODE BLOCKS AND EXITS THE VM WHEN THE FUTURES ARE DONE!! 
    println(s"${new Date} waiting for futures") 
    listOfProfileFuturesFuture.foreach{listOfFut => 
    Await.ready(Future.sequence(listOfFut), Duration.Inf) 
    println(s"${new Date} all futures done") 
    System.exit(0) 
    } 
    scala.io.StdIn.readLine() 

Um

import scala.concurrent.{Future, Await} 
    import scala.concurrent.duration.Duration 
    import scala.concurrent.ExecutionContext.Implicits.global 

    def campaignFuture(advertiserId: Int): Future[List[BigInt]] = Future { 
    List(1, 2, 3) 
    } 
    def profileFuture(profileId: Int): Future[List[String]] = Future { 
    List(s"profile-for:$profileId") 
    } 


    // type: Future[List[Future[List[String]]]] 
    val listOfProfileFutures = campaignFuture(1).map { campaign => 
    campaign.map(id => profileFuture(id.toInt)) 
    } 

    // type: Future[List[List[String]]] 
    val listOfProfileFuture = listOfProfileFutures.flatMap(s => Future.sequence(s)) 


    // print the result 
    //listOfProfileFuture.foreach(println) 
    //scala.io.StdIn.readLine() 

    // wait for the result (THIS BLOCKS INFINITY!) 
    Await.result(listOfProfileFuture, Duration.Inf) 

  • wir Future.sequence zu bekommen verwenden eine Liste [Zukunft [T]] in Zukunft [Liste [T]] umwandeln.
  • flatMap eine Zukunft [T] von Future [Zukunft [T]]
  • erhalten, wenn Sie auf das Ergebnis warten müssen (Blocking!) Verwenden Await für das Ergebnis warten
+0

Dieser funktioniert! Aber wie erhalte ich das Ergebnis von listOfProfileFuture? Sie haben keine Kontrolle darüber, wann diese Futures als solche abgeschlossen werden. Der Anrufer hätte diese Futures gerade erstellt und im Hintergrund laufen lassen. Ich möchte die Ergebnisse dieser Futures erhalten. Lass es mich wissen, bitte. – Anand

+0

Wenn Sie auf das Ergebnis warten wollen, verwenden Sie Await.result (listOfProfileFuture, Duration.Inf) –

+0

Gibt es eine Möglichkeit, ich kann es in eine Datei drucken, wie ich Ausgabe von diesen Futures bekomme? Wird eine Warnung erwartet, wird der aktuelle Thread blockiert? – Anand

Verwandte Themen