在屏幕上组合并输出两个未来的异步操作
Composing and outputting two future asynchronous actions on screen
我不想问 - 我真的想问,但这个问题暂时让我明白了..
我正在尝试编写一些动作(在 Play Framework & scala),我的主要指南是 this vid。然而,它是几年前制作的,所以一些功能已经被弃用,因此我不得不在我去的时候寻找解决方法。目前我正在尝试在一些 HTML 标记中输出两个异步操作。
我用这个控制器成功输出了一个动作:
package controllers
import akka.actor.ActorSystem
import javax.inject._
import play.api.mvc._
import services.ServiceClient
import scala.concurrent.ExecutionContext
@Singleton
class AsyncController @Inject() (sc: ServiceClient)(actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends Controller {
def index = Action.async { request =>
val asy1 = sc.makeServiceCall("async1")
for {
async1Message <- asy1
} yield {
Ok(views.html.async1.async1(async1Message))
}
}
}
如果您想知道 sc.makeServiceCall
指的是这个文件:
class ServiceClient @Inject() (ws: WSClient) {
def makeServiceCall(serviceName: String): Future[String] = {
ws.url(s"http://localhost:9000/mock/$serviceName").get().map(_.body)
}
}
所以我按照视频的指导将两个异步操作与一些 HTML 组合在一起。这就是它得到 difficult/interesting/upsetting:
的地方
package controllers
import javax.inject.Inject
import akka.actor.ActorSystem
import play.api.mvc._
import scala.concurrent.{ExecutionContext}
import Ui.Pagelet
class AsyncHomeController @Inject() (as1: AsyncController)(as2: Async2Controller)(actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends Controller {
def index = Action.async { request =>
val asy1 = as1.index(request)
val asy2 = as2.index(request)
for {
async1Result <- asy1
async2Result <- asy2
async1Body <- Pagelet.readBody(async1Result)
async2Body <- Pagelet.readBody(async2Result)
} yield {
Ok(views.html.home2(async1Body, async2Body))
}
}
}
所以Async2Controller
和AsyncController
非常相似,Pagelet.readBody
指的是:
package Ui
import play.api.libs.iteratee.Iteratee
import play.api.mvc.{Codec, Result}
import play.twirl.api.Html
import scala.concurrent._
object Pagelet {
def readBody(result: Result)(implicit codec: Codec): Future[Html] = {
result.body.run(Iteratee.consume()).map(bytes => Html(new String(bytes, codec.charset)))
}
}
这就是错误所在 - 即:
value run is not a member of play.api.http.HttpEntity
我找不到关于它是否需要注入的文档或任何表明它已被弃用的迹象。 如果有人对此有答案或解决方法,请透露。非常感谢
Iteratee
库已弃用并被 akka-stream
取代。您需要更改 readBody
:
的实现
def readBody(result: Result)(implicit mat: Materializer, ec: ExecutionContext, codec: Codec): Future[Html] = {
result.body.consumeData.map(byteString => Html(codec.decode(byteString))
}
您还需要更改控制器的依赖项以获得 Materializer
:
class AsyncHomeController @Inject() (as1: AsyncController, as2: Async2Controller)(actorSystem: ActorSystem)(implicit exec: ExecutionContext, mat: Materializer)
编辑:代码已更新
我不想问 - 我真的想问,但这个问题暂时让我明白了..
我正在尝试编写一些动作(在 Play Framework & scala),我的主要指南是 this vid。然而,它是几年前制作的,所以一些功能已经被弃用,因此我不得不在我去的时候寻找解决方法。目前我正在尝试在一些 HTML 标记中输出两个异步操作。
我用这个控制器成功输出了一个动作:
package controllers
import akka.actor.ActorSystem
import javax.inject._
import play.api.mvc._
import services.ServiceClient
import scala.concurrent.ExecutionContext
@Singleton
class AsyncController @Inject() (sc: ServiceClient)(actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends Controller {
def index = Action.async { request =>
val asy1 = sc.makeServiceCall("async1")
for {
async1Message <- asy1
} yield {
Ok(views.html.async1.async1(async1Message))
}
}
}
如果您想知道 sc.makeServiceCall
指的是这个文件:
class ServiceClient @Inject() (ws: WSClient) {
def makeServiceCall(serviceName: String): Future[String] = {
ws.url(s"http://localhost:9000/mock/$serviceName").get().map(_.body)
}
}
所以我按照视频的指导将两个异步操作与一些 HTML 组合在一起。这就是它得到 difficult/interesting/upsetting:
的地方package controllers
import javax.inject.Inject
import akka.actor.ActorSystem
import play.api.mvc._
import scala.concurrent.{ExecutionContext}
import Ui.Pagelet
class AsyncHomeController @Inject() (as1: AsyncController)(as2: Async2Controller)(actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends Controller {
def index = Action.async { request =>
val asy1 = as1.index(request)
val asy2 = as2.index(request)
for {
async1Result <- asy1
async2Result <- asy2
async1Body <- Pagelet.readBody(async1Result)
async2Body <- Pagelet.readBody(async2Result)
} yield {
Ok(views.html.home2(async1Body, async2Body))
}
}
}
所以Async2Controller
和AsyncController
非常相似,Pagelet.readBody
指的是:
package Ui
import play.api.libs.iteratee.Iteratee
import play.api.mvc.{Codec, Result}
import play.twirl.api.Html
import scala.concurrent._
object Pagelet {
def readBody(result: Result)(implicit codec: Codec): Future[Html] = {
result.body.run(Iteratee.consume()).map(bytes => Html(new String(bytes, codec.charset)))
}
}
这就是错误所在 - 即:
value run is not a member of play.api.http.HttpEntity
我找不到关于它是否需要注入的文档或任何表明它已被弃用的迹象。 如果有人对此有答案或解决方法,请透露。非常感谢
Iteratee
库已弃用并被 akka-stream
取代。您需要更改 readBody
:
def readBody(result: Result)(implicit mat: Materializer, ec: ExecutionContext, codec: Codec): Future[Html] = {
result.body.consumeData.map(byteString => Html(codec.decode(byteString))
}
您还需要更改控制器的依赖项以获得 Materializer
:
class AsyncHomeController @Inject() (as1: AsyncController, as2: Async2Controller)(actorSystem: ActorSystem)(implicit exec: ExecutionContext, mat: Materializer)
编辑:代码已更新