使用 play 和 akka-https:如何正确地将多个请求链接到传入请求以创建响应?
With play and akka-https: How to properly chain multiple requests to the incoming request to create a response?
所以我尝试让一个小型播放应用程序与另一个休息服务进行通信。
这个想法是,在播放端接收请求,然后向其余 api 发出请求,并将部分结果提供给另一个本地演员,然后在浏览器中显示来自本地演员和其余服务的响应.
This image shows how
我试着用流来做。我一切正常,但我对与当地演员交谈并创建 Future[(Future[String],Future[String])
元组的部分绝对不满意,所以如果你能指出我的方向,我会很高兴,如何做到这一点以优雅干净的方式。
这是我的代码。输入是一个 csv 文件。
我的本地演员创建了一个我想放入响应中的附加图形。
def upload = Action.async(parse.multipartFormData) { request =>
request.body.file("input").map { inputCsv =>
//csv to list of strings
val inputList: List[String] = convertFileToList(inputCsv)
//http request to rest service
val responseFuture: Future[HttpResponse] = httpRequest(inputList, "/path",4321 ,"0.0.0.0")
//pattern match response and ask local actor
val formattedResult = responseFuture.flatMap { response =>
response.status match {
case akka.http.scaladsl.model.StatusCodes.OK =>
val resultTeams = Unmarshal(response.entity).to[CustomResultCaseClass]
//the part I'd like to improve
val tupleFuture = resultTeams.map(result =>
(Future(result.teams.reduce(_ + "," + _)),
plotter.ask(PlotData(result.eval)).mapTo[ChartPath].flatMap(plotAnswer => Future(plotAnswer.path))))
tupleFuture.map(tuple => tuple._1.map(teams =>
p._2.map(chartPath => Ok(views.html.upload(teams))(chartPath))))).flatMap(a => a).flatMap(b => b)
}
}
formattedResult
}.getOrElse(Future(play.api.mvc.Results.BadRequest))
}
For comprehensions 对此类用例很有用。一个演示所涉及的重构的基本示例:
val teamFut = Future(result.teams.reduce(_ + "," + _))
//I think the final .flatMap(Future(_.path)) is unnecessary it should be
// .map(_.path), but I wanted to replicate the question code functionality
val pathFut = plotter.ask(PlotData(result.eval))
.mapTo[ChartPath]
.flatMap(Future(_.path))
val okFut =
for {
teams <- teamFut
chartPath <- pathFut
} yield Ok(views.html.upload(teams))(chartPath)
注意:Initial Futures 应该在 之外实例化,否则不会发生并行执行。
所以我尝试让一个小型播放应用程序与另一个休息服务进行通信。 这个想法是,在播放端接收请求,然后向其余 api 发出请求,并将部分结果提供给另一个本地演员,然后在浏览器中显示来自本地演员和其余服务的响应. This image shows how
我试着用流来做。我一切正常,但我对与当地演员交谈并创建 Future[(Future[String],Future[String])
元组的部分绝对不满意,所以如果你能指出我的方向,我会很高兴,如何做到这一点以优雅干净的方式。
这是我的代码。输入是一个 csv 文件。 我的本地演员创建了一个我想放入响应中的附加图形。
def upload = Action.async(parse.multipartFormData) { request =>
request.body.file("input").map { inputCsv =>
//csv to list of strings
val inputList: List[String] = convertFileToList(inputCsv)
//http request to rest service
val responseFuture: Future[HttpResponse] = httpRequest(inputList, "/path",4321 ,"0.0.0.0")
//pattern match response and ask local actor
val formattedResult = responseFuture.flatMap { response =>
response.status match {
case akka.http.scaladsl.model.StatusCodes.OK =>
val resultTeams = Unmarshal(response.entity).to[CustomResultCaseClass]
//the part I'd like to improve
val tupleFuture = resultTeams.map(result =>
(Future(result.teams.reduce(_ + "," + _)),
plotter.ask(PlotData(result.eval)).mapTo[ChartPath].flatMap(plotAnswer => Future(plotAnswer.path))))
tupleFuture.map(tuple => tuple._1.map(teams =>
p._2.map(chartPath => Ok(views.html.upload(teams))(chartPath))))).flatMap(a => a).flatMap(b => b)
}
}
formattedResult
}.getOrElse(Future(play.api.mvc.Results.BadRequest))
}
For comprehensions 对此类用例很有用。一个演示所涉及的重构的基本示例:
val teamFut = Future(result.teams.reduce(_ + "," + _))
//I think the final .flatMap(Future(_.path)) is unnecessary it should be
// .map(_.path), but I wanted to replicate the question code functionality
val pathFut = plotter.ask(PlotData(result.eval))
.mapTo[ChartPath]
.flatMap(Future(_.path))
val okFut =
for {
teams <- teamFut
chartPath <- pathFut
} yield Ok(views.html.upload(teams))(chartPath)
注意:Initial Futures 应该在 之外实例化,否则不会发生并行执行。