Scala 在游戏2.5中完成后输出两个期货

Scala 在游戏2.5中完成后输出两个期货,scala,playframework,akka,future,akka-stream,Scala,Playframework,Akka,Future,Akka Stream,我很谦虚地回到社区,因为我现在显然太深了 因此,我试图将Scala中Play2.5.2中的两个未来返回到屏幕,作为完成后出现在屏幕上的模块。我试过很多方法来做到这一点。首先要注意的是,我似乎能够成功地流式传输两个具有重复时间表的源: def streamAction = Action { request => val source1: Source[String, NotUsed] = unfoldAsync(NotUsed) { _ ⇒ sc.makeServi

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

因此,我试图将Scala中Play2.5.2中的两个未来返回到屏幕,作为完成后出现在屏幕上的模块。我试过很多方法来做到这一点。首先要注意的是,我似乎能够成功地流式传输两个具有重复时间表的源:

  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
     }

   }
这就像前面提到的那样,输出如下流:

FirstFirstSecondFirstFirstSecondFirstFirstFirstSecond

但是,在试图输出两个未来时,每个未来只完成一次,我不能。我试过这个:

 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


我做错了什么?

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

我使用了以下代码并将其称为curl-nlocalhost:9000/stream


正如预期的那样,这会在async1和3秒后返回async2。

您使用什么来调用该操作?客户端可能有一些缓冲区。使用curl,您可以使用-N选项来避免它。@cyrilecorpet-是的,缓冲区可能有问题,但我也有curl的问题,所以我不能确定。你会这样做吗?我在播放和卷曲流时遇到了一些缓冲问题,由-N解决。它们与合并流无关,但在播放-2.3.8中,其中streams起诉Iteratee而不是akka streams。@CyrilleCorpet,正如我所说,我在命令提示符中遇到了与cURL有关的问题,该命令提示符返回GET/HTTP/1.1而不是任何结果,没有人能够帮助我解释原因。我想测试一下这是否是一个缓冲问题。我使用的是Play 2.5.2坦克,但这只会在3.03秒时同时呈现两个结果,所以在较长的将来完成source2之后不久。但是我不能像前面提到的那样使用cURL进行测试,因为我遇到了这些问题是的,但是我的测试表明,您的客户端存在缓冲区问题,而不是流媒体问题。我非常希望自己看到这一点,但正如我所说的,正如您将看到的,我在端口方面遇到了问题。我不想偏离原来的问题太远,但因为它是相关的-我能问一下您是如何配置cURL和Play的吗?让我们在这里继续这个对话:
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)
}