在Play 2.5中完成两个期货输出

时间:2017-06-05 20:38:06

标签: scala playframework akka future akka-stream

我谦卑地回到社区,因为我现在显然太深了。

因此,我尝试将两个期货(在Scala中的Play 2.5.2中)返回到屏幕上,作为完成后出现在屏幕上的模块。我已经尝试了很多尝试这样做的方法。首先要注意的是,我似乎能够成功传输两个具有重复计划的 Sources

  def streamAction = Action { request =>

    val source1: Source[String, NotUsed] = unfoldAsync(NotUsed) { _ ⇒
      sc.makeServiceCall("stream1").map(x ⇒ Some(NotUsed → x))
    }

    val source2: Source[String, NotUsed] = unfoldAsync(NotUsed) { _ ⇒
      sc.makeServiceCall("stream2").map(x ⇒ Some(NotUsed → x))
    }

    Ok.chunked(source1.merge(source2))
  }

sc.makeServiceCall指的是:

   class ServiceClient @Inject() (ws: WSClient) {

     def makeServiceCall(serviceName: String): Future[String] = {
       ws.url(s"http://localhost:9000/mock/$serviceName").get().map(_.body)
     }

   }

致电:

   class Mock @Inject() (actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends Controller {

     def mock(serviceName: String) = Action.async { request =>
       serviceName match {
         case "async1" => respond("asy1", 0.second)
         case "async2" => respond("asy2", 3.second)
         case "async3" => respond("asy3", 5.second)
         case "stream1" => schedule("first", 500.millisecond)
         case "stream2" => schedule("second", 2000.millisecond)
       }
     }

     private def schedule(data: String, delay: FiniteDuration): Future[Result] = {
       akka.pattern.after(delay, actorSystem.scheduler){Future.successful(Ok(data))}
     }

     private def respond(data: String, delay: FiniteDuration): Future[Result] = {
       val promise: Promise[Result] = Promise[Result]()
       actorSystem.scheduler.scheduleOnce(delay) { promise.success(Ok(data)) }
       promise.future
     }

   }

所以这可以(如上所述)输出这样的流:

  

firstfirstfirstsecondfirstfirstfirstfirstsecondfirstfirstfirstfirstsecond

但是在尝试输出两个期货时(每个只有一个)我不能。我试过这个:

 def outputAction = Action { request =>

   val source1: Source[String, NotUsed] = Source.fromFuture(sc.makeServiceCall("async1"))
   val source2: Source[String, NotUsed] = Source.fromFuture(sc.makeServiceCall("async2"))

   Ok.chunked(source1.merge(source2))
 }

这只是一次性输出(当第二个未来完成时)

  

asys1asys2

我做错了什么?

1 个答案:

答案 0 :(得分:1)

如评论中所述,这似乎是您客户端的缓存问题:

我使用了以下代码并调用了curl -N localhost:9000/stream

def streamAction = Action { request =>

  val source1: Source[String, NotUsed] = Source.single("async1")

  val source2: Source[String, NotUsed] = Source.single("async2").initialDelay(3.seconds)

  val merged: Source[String, NotUsed] = source1.merge(source2)

  Ok.chunked(merged)
}

按预期方式返回async1和3秒后async2