在我的playframework应用程序中,我想等到我的未来完成并将其返回到视图中。
我的代码如下:
def getContentComponentUsageSearch: Action[AnyContent] = Action.async { implicit request =>
println(request.body.asJson)
request.body.asJson.map(_.validate[StepIds] match {
case JsSuccess(stepIds, _) =>
println("VALIDE SUCCESS -------------------------------")
val fList: List[Seq[Future[ProcessTemplatesModel]]] = List() :+ stepIds.s.map(s => {
processTemplateDTO.getProcessStepTemplate(s.processStep_id).flatMap(stepTemplate => {
processTemplateDTO.getProcessTemplate(stepTemplate.get.processTemplate_id.get).map(a => {
a.get
})
})
})
fList.map(u => {
val a: Seq[Future[ProcessTemplatesModel]] = u
Future.sequence(a).map(s => {
println(s)
})
})
Future.successful(Ok(Json.obj("id" -> "")))
case JsError(_) =>
println("NOT VALID -------------------------------")
Future.successful(BadRequest("Process Template not create client"))
case _ => Future.successful(BadRequest("Process Template create client"))
}).getOrElse(Future.successful(BadRequest("Process Template create client")))
}
pirntln(s)
正在打印已完成的内容。但是我怎么能等到它完成然后再返回视图呢?
提前致谢
更新:
也尝试了这个:
val process = for {
fList: List[Seq[Future[ProcessTemplatesModel]]] <- List() :+ stepIds.s.map(s => {
processTemplateDTO.getProcessStepTemplate(s.processStep_id).flatMap(stepTemplate => {
processTemplateDTO.getProcessTemplate(stepTemplate.get.processTemplate_id.get).map(a => {
a.get
})
})
})
} yield (fList)
process.map({ case (fList) =>
Ok(Json.obj(
"processTemplate" -> fList
))
})
然后我得到了这个:
更新: 我的问题是fList中的期货在返回OK结果之前没有完成
答案 0 :(得分:4)
问题中的代码似乎不可编辑,因此这是一个未经测试的非常粗略的草图,希望为进一步搜索正确的解决方案提供足够的灵感:
def getContentComponentUsageSearch: = Action.async { implicit req =>
req.body.asJson.map(_.validate[StepIds] match {
case JsSuccess(stepIds, _) => {
// Create list of futures
val listFuts: List[Future[ProcessTemplatesModel]] = (stepIds.s.map(s => {
processTemplateDTO.
getProcessStepTemplate(s.processStep_id).
flatMap{ stepTemplate =>
processTemplateDTO.
getProcessTemplate(stepTemplate.get.processTemplate_id.get).
map(_.get)
}
})).toList
// Sequence all the futures into a single future of list
val futList = Future.sequence(listFuts)
// Flat map this single future to the OK result
for {
listPTMs <- futList
} yield {
// Apparently some debug output?
listPTMs foreach printl
Ok(Json.obj("id" -> ""))
}
}
case JsError(_) => {
println("NOT VALID -------------------------------")
Future.successful(BadRequest("Process Template not create client"))
}
case _ => Future.successful(BadRequest("Process Template create client"))
}).getOrElse(Future.successful(BadRequest("Process Template create client")))
}
如果我理解你的问题,你想要的是确保列表中的所有未来在你返回OK之前完成。因此,我首先创建了一个List[Future[...]]
:
val listFuts: List[Future[ProcessTemplatesModel]] = // ...
然后我将所有的期货合并到一个列表的未来,只有在每个元素都完成时才会完成:
// Sequence all the futures into a single future of list
val futList = Future.sequence(listFuts)
然后我使用for
- 理解来确保listPTMs
在返回OK
之前完成计算:
// Flat map this single future to the OK result
for {
listPTMs <- futList
} yield {
// Apparently some debug output?
listPTMs foreach printl
Ok(Json.obj("id" -> ""))
}
for-yield
(此处相当于map
)确定了此前行为的完成情况,以便在listPTMs
之前对OK
进行全面评估是建造的。
答案 1 :(得分:3)
为了等到Future完成,最常见的是做两件事之一:
使用for-comprehension,在yield
部分执行任何操作之前,会在幕后进行一系列映射和平面映射(有关更详细的说明,请参阅Andrey的注释)。一个简化的例子:
def index: Action[AnyContent] = Action.async {
val future1 = Future(1)
val future2 = Future(2)
for {
f1 <- future1
f2 <- future2
} yield {
println(s"$f1 + $f2 = ${f1 + f2}") // prints 3
Ok(views.html.index("Home"))
}
}
映射未来:
def index: Action[AnyContent] = Action.async {
val future1 = Future(1)
future1.map{
f1 =>
println(s"$f1")
Ok(views.html.index("Home"))
}
}
如果有多个期货:
def index: Action[AnyContent] = Action.async {
val future1 = Future(1)
val future2 = Future(2)
future1.flatMap{
f1 =>
future2.map {
f2 =>
println(s"$f1 + $f2 = ${f1 + f2}")
Ok(views.html.index("Home"))
}
}
}
}
当你有多个期货时,for-yield
理解的论点变得更加强大,因为它更容易阅读。此外,您可能知道,但如果您使用期货,您可能需要关注进口:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global