2016-08-29 85 views
1

在我的演員我有不同的地址兩個請求是這樣的:Akka:如何管理雙重http請求?

http.singleRequest(HttpRequest(uri = encodedUri).addHeader(Accept(MediaTypes.`application/json`))) 

我需要這兩個請求,同時返回一個值。由於正常的期貨我希望是這樣的:

val response: Future[SomeData] = for { 
     r1 <- firstRequest 
     r2 <- secondRequest 
     } yield { 
     // merge the results of these two responses 
     } 

     response onComplete { 
     case Success(body) => sndr ! Something(body) 
     case Failure(message) => BadRequest(message.toString) 
     } 

在本文檔中的這一部分:

http://doc.akka.io/docs/akka/2.4/scala/http/client-side/request-level.html

建議使用pipeToself管理單個請求,而不是使用原生onComplete/map/etc

我該如何申請多個請求,比如在我的情況下,我需要等待2個或更多完成?

回答

3

簡單和直接盼着

val f1 = Future { //request1 } 

val f2 = Future { //request2 } 

val resultF = f1 zip f2 

resultF pipeTo self 

當前的演員將獲得的結果作爲消息和消息將是一個元組(f1Result, f2Result)

如果結果resultF失敗當前的演員得到包裹在akka.actor.Status.Failure

失敗消息

在方法f1f2是獨立期貨

萬一f2取決於f1使用值flatMap

val resultF = f1.flatMap { f1Result => createF2(f1Result) } 

//alternatively we can use for comprehension 

resultF pipeTo self 

import akka.actor.Actor 
import akka.actor.Status.Failure 

import scala.concurrent.Future 
import akka.pattern.pipe 

object ManagerActor { 
    case object Exec 
} 

class ManagerActor extends Actor { 

    import ManagerActor._ 

    implicit val dispather = context.dispatcher 

override def receive: Receive = { 
    case Exec => 

    val f1 = Future { 1 } 

    val f2 = Future { 2 } 

    val resultF = f1 zip f2 

    resultF pipeTo self 

    case result: (Int, Int) => //be careful about type erasure 
    println(s"""result:$result""") 

    case Failure(th) => 
    println(s"""msg: ${th.getMessage}""") 

    } 
} 

運行

object Main { 
def main(args: Array[String]): Unit = { 
    val system = ActorSystem() 
    val actor = system.actorOf(Props[ManagerActor]) 
    actor ! ManagerActor.Exec 
    Thread.sleep(1000000) 
} 
} 

我們可以在使用Future.sequence取而代之的是zip將其推廣到任何數量的http請求。

+0

'flatMap'可能不如'map'。我認爲真正的問題是發送者在未來線程中的可見性。 – Randomize