在Scala中转换为For Comprehension

jes*_*ris 0 scala future stream akka for-comprehension

测试这个我可以看到它的工作原理:

def twoHtmlFutures = Action { request =>

  val async1 = as1.index(embed = true)(request) // Future[Result]
  val async2 = as2.index(embed = true)(request) // Future[Result]

  val async1Html = async1.flatMap(x => Pagelet.readBody(x)) // Future[Html]
  val async2Html = async2.flatMap(x => Pagelet.readBody(x)) // Future[Html]

  val source1 = Source.fromFuture(async1Html) // Source[Html, NotUsed]
  val source2 = Source.fromFuture(async2Html) // Source[Html, NotUsed]

  val merged = source1.merge(source2) // Source[Html, NotUsed]
  Ok.chunked(merged)
}
Run Code Online (Sandbox Code Playgroud)

但试图将其纳入For Comprehension并不适合我.这是我试过的:

def twoHtmlFutures2 = Action.async { request =>

  val async1 = as1.index(embed = true)(request)
  val async2 = as2.index(embed = true)(request)

  for {
    async1Res <- async1 // from Future[Result] to Result
    async2Res <- async2 // from Future[Result] to Result

    async1Html <- Pagelet.readBody(async1Res) // from Result to Html
    async2Html <- Pagelet.readBody(async2Res) // from Result to Html

  } yield {
    val source1 = single(async1Html) // from Html to Source[Html, NotUsed]
    val source2 = single(async2Html) // from Html to Source[Html, NotUsed]

    val merged = source1.merge(source2) // Source[Html, NotUsed]
    Ok.chunked(merged)
  }

}
Run Code Online (Sandbox Code Playgroud)

但这只是在屏幕上同时跳转而不是在第一个例子的不同时间(流式传输).有没有帮助我的眼皮呢?谢谢

Vik*_*ang 6

Monads是一种排序形式,Futures将其建模为因果依赖(首先 - 这未来完成 - 然后 - 未来 - 完成):

val x = Future(something).map(_ => somethingElse) or Future(something).flatMap(_ => Future(somethingElse)
Run Code Online (Sandbox Code Playgroud)

但是,有一个小技巧可以用于理解:

def twoHtmlFutures = Action { request =>
  Ok.chunked(
    Source.fromFutureSource(
      for { _ <- Future.unit // For Scala version <= 2.11 use Future.successful(())
        async1 = as1.index(embed = true)(request) // Future[Result]
        async2 = as2.index(embed = true)(request) // Future[Result]
        async1Html = async1.flatMap(x => Pagelet.readBody(x)) // Future[Html]
        async2Html = async2.flatMap(x => Pagelet.readBody(x)) // Future[Html]
        source1 = Source.fromFuture(async1Html) // Source[Html, NotUsed]
        source2 = Source.fromFuture(async2Html) // Source[Html, NotUsed]
       } yield source1.merge(source2) // Source[Html, NotUsed]
    )
  )
Run Code Online (Sandbox Code Playgroud)

我在这篇博文中更详细地描述了这种技术.

您问题的另一种解决方案可能是:

def twoHtmlFutures = Action { request =>
  Ok.chunked(
  Source.fromFuture(as1.index(embed = true)(request)).merge(Source.fromFuture(as2.index(embed = true)(request))).mapAsyncUnordered(2)(b => Pagelet.readBody(b))
  )
 }
Run Code Online (Sandbox Code Playgroud)