玩框架scala如何异步等待
playframework scala how to wait for asyncronousity
我再次遇到 Scala 的异步性问题。
我有以下代码:
Future.sequence {
processSteps.map { step =>
val prerequisiteFuture = processStepPrerequisitesDTO.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
}
}
processSteps.map { step => {
println("diddled", step.prerequisites)}
}
如何正确等待 future.sequnce 完成。因为当我之后尝试打印它们时它是空的......但它不是......同时调用这些行并且打印速度比 future.sequence.
我不想使用 Await ...
谢谢。
更新
这是我的完整控制器功能:
def getEditProcessTemplateData(processTemplateId: Int): Action[AnyContent] = Action.async {
//获取本次流程模板的所有步骤
val stepIds: Future[Seq[Int]] = processTemplateDTO.getProcessStepTemplateIds(processTemplateId)
val process = for {
allApprovedProcessTemplates <- processTemplateDTO.getApprovedProcessTemplates //Get all approved process templates
processTemplate <- processTemplateDTO.getProcessTemplate(processTemplateId) // Get the Process Template
prerequisites <- getProcessTemplateForEdit(processPrerequisitesDTO.getProcessPrerequisiteProcessTemplateIdsByProcessTemplateId(processTemplateId))
postConditions <- getProcessTemplateForEdit(processPostConditionsDTO.getProcessPostConditionProcessTemplateIdsByProcessTemplateId(processTemplateId))
approvedProcessTemplate <- processTemplateDTO.getProcessTemplate(processTemplate.get.approveprocess)
trainedProcessTemplate <- processTemplateDTO.getProcessTemplate(processTemplate.get.trainingsprocess)
processSteps <- processTemplateDTO.getProcessStepTemplates(processTemplateId)
// Step prerequisites
processStepsPrerequisites <- getProcessStepsPrerequisites(stepIds)
processStepsPrerequisiteProcessTemplate <- getProcessStepsPrerequisiteProcessTemplate(stepIds)
processTemplatesForStepPrerequisites <- getProcessTemplateForStepPrerequisite(stepIds)
// Step post conditions
processStepsPostConditions <- getProcessStepsPostConditions(stepIds)
processStepPostConditionProcessTemplate <- getProcessStepPostConditionProcessTemplate(stepIds)
processTemplatesForStepPostConditions <- getProcessTemplateForStepPostCondition(stepIds)
// Derived processes
derivedProcesses <- getDerivedProcesses(stepIds)
processTemplatesForStepDerivedProcesses <- getProcessStepsDerivedProcesses(stepIds)
// Process to process step
processStepsTemplates_ProcessTemplates <- getProcessStepsTemplates_ProcessTemplates(stepIds)
processTemplatesForProcessTemplatesToProcessStep <- getProcessTemplateToProcessStepId(stepIds)
responsible <- raciProcessTemplateDTO.getResponsibleProcessTemplates(processTemplateId) // get all responsibles for this process template
accountable <- raciProcessTemplateDTO.getAccountableProcessTemplates(processTemplateId) // get all accountables for this process template
consulted <- raciProcessTemplateDTO.getConsultedProcessTemplates(processTemplateId) // get all consulted for this process template
informed <- raciProcessTemplateDTO.getInformedProcessTemplates(processTemplateId) // get all consulted for this process template
} yield (allApprovedProcessTemplates, processTemplate, prerequisites, postConditions, processSteps, processStepsPrerequisites,
processStepsPrerequisiteProcessTemplate, processTemplatesForStepPrerequisites, processStepsPostConditions, processStepPostConditionProcessTemplate, processTemplatesForStepPostConditions, derivedProcesses,
processTemplatesForStepDerivedProcesses, processStepsTemplates_ProcessTemplates, processTemplatesForProcessTemplatesToProcessStep, approvedProcessTemplate, trainedProcessTemplate, responsible, accountable, consulted, informed)
process.map({ case (allApprovedProcessTemplates, processTemplate, prerequisites, postConditions, processSteps, processStepsPrerequisites,
processStepsPrerequisiteProcessTemplate, processTemplatesForStepPrerequisites, processStepsPostConditions, processStepPostConditionProcessTemplate, processTemplatesForStepPostConditions, derivedProcesses,
processTemplatesForStepDerivedProcesses, processStepsTemplates_ProcessTemplates, processTemplatesForProcessTemplatesToProcessStep, approvedProcessTemplate, trainedProcessTemplate, responsible, accountable, consulted, informed) =>
val sequenced = Future.sequence {
processSteps.map { step =>
val prerequisiteFuture = processStepPrerequisitesDTO.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
}
}
sequenced.map { items => {
println(items)}
}
Ok(Json.obj(
"allApprovedProcessTemplates" -> allApprovedProcessTemplates,
"processTemplate" -> processTemplate,
"prerequisites" -> prerequisites,
"postConditions" -> postConditions,
"approvedProcessTemplate" -> approvedProcessTemplate,
"trainedProcessTemplate" -> trainedProcessTemplate,
// Step prerequisites
"processStepsPrerequisites" -> processStepsPrerequisites,
"processStepsPrerequisiteProcessTemplate" -> processStepsPrerequisiteProcessTemplate,
"processTemplatesForStepPrerequisites" -> processTemplatesForStepPrerequisites,
// Step post conditions
"processStepsPostConditions" -> processStepsPostConditions,
"processStepPostConditionProcessTemplate" -> processStepPostConditionProcessTemplate,
"processTemplatesForStepPostConditions" -> processTemplatesForStepPostConditions,
// Derived processes
"derivedProcesses" -> derivedProcesses,
"processTemplatesForStepDerivedProcesses" -> processTemplatesForStepDerivedProcesses,
// Process to process step
"processStepsTemplates_ProcessTemplates" -> processStepsTemplates_ProcessTemplates,
"processTemplatesForProcessTemplatesToProcessStep" -> processTemplatesForProcessTemplatesToProcessStep,
"steps" -> processSteps,
"responsible" -> responsible,
"accountable" -> accountable,
"consulted" -> consulted,
"informed" -> informed
))
})
}
你能试试这个吗:
val sequenced = Future.sequence {
processSteps.map { step =>
val prerequisiteFuture = processStepPrerequisitesDTO.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
}
}
sequenced.map { items =>
items foreach (println("diddled", _.prerequisites))
}
?
------------------------------------更新------ ------------------
您没有提供任何关于此代码位置真正 运行 的上下文。因此,如果您希望它最终打印在控制台中,您需要确保主线程或任何线程当序列中的所有期货都完成时,还有 运行 吗?
这是一个简化的例子:
导入 scala.concurrent.Future
导入 scala.concurrent.ExecutionContext.Implicits.global
object Test {
def main(args:Array[String]):Unit = {
val sequence = Seq(Future({Thread.sleep(100); 1}), Future({Thread.sleep(200); 2}))
val sequenced = Future.sequence(sequence)
sequenced foreach(items => items foreach(println(_)))
Thread.sleep(1000)
}
}
产生以下控制台输出:
1
2
Process finished with exit code 0
但在此示例中使用 Thread.sleep
或 Await
仅用于在控制台中显示结果。
您最初的问题是您将期货序列包装到 Future.sequence
中,但之后您仍然尝试使用内部序列,您从未使用过 Future.sequence
未来实例创建的。
我认为在你的代码中你将结果 future 传递给了更高的上下文,所以你需要检查并 println
那里是否是这样的,例如网络应用程序。
如果考虑到以上所有内容,它仍然打印空向量 - 那么这意味着该向量确实是空的,因此您需要在本地调试并找出原因。
您需要了解的几件事:
如果函数中没有return语句,则function/lambda的return类型由函数的最后一条语句定义。
所以函数
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
将 return 未来 [Unit],因为 return 类型的 println() 是 Unit。
Future.sequence 将 List[Future[A]]
转换为 Future[List[A]]
。
因此,在上面的示例中,您创建了一个将打印但不会 return 任何内容的未来。
稍后您只需打印步骤。
由于 future 被延迟,输出将是 diddled
后跟 COPY
。
如果你想在 Copy 之后执行 diddled 你应该使用 future.map()
。像这样
Future.sequence {processSteps.map {
step =>
val prerequisiteFuture = processStepPrerequisitesDTO
.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
step.prerequisites
})
}
}.map {
items =>
items.map { step =>
println("diddled", step.prerequisites)
}
Ok("your json response here")
}
我再次遇到 Scala 的异步性问题。
我有以下代码:
Future.sequence {
processSteps.map { step =>
val prerequisiteFuture = processStepPrerequisitesDTO.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
}
}
processSteps.map { step => {
println("diddled", step.prerequisites)}
}
如何正确等待 future.sequnce 完成。因为当我之后尝试打印它们时它是空的......但它不是......同时调用这些行并且打印速度比 future.sequence.
我不想使用 Await ...
谢谢。
更新
这是我的完整控制器功能: def getEditProcessTemplateData(processTemplateId: Int): Action[AnyContent] = Action.async { //获取本次流程模板的所有步骤 val stepIds: Future[Seq[Int]] = processTemplateDTO.getProcessStepTemplateIds(processTemplateId)
val process = for {
allApprovedProcessTemplates <- processTemplateDTO.getApprovedProcessTemplates //Get all approved process templates
processTemplate <- processTemplateDTO.getProcessTemplate(processTemplateId) // Get the Process Template
prerequisites <- getProcessTemplateForEdit(processPrerequisitesDTO.getProcessPrerequisiteProcessTemplateIdsByProcessTemplateId(processTemplateId))
postConditions <- getProcessTemplateForEdit(processPostConditionsDTO.getProcessPostConditionProcessTemplateIdsByProcessTemplateId(processTemplateId))
approvedProcessTemplate <- processTemplateDTO.getProcessTemplate(processTemplate.get.approveprocess)
trainedProcessTemplate <- processTemplateDTO.getProcessTemplate(processTemplate.get.trainingsprocess)
processSteps <- processTemplateDTO.getProcessStepTemplates(processTemplateId)
// Step prerequisites
processStepsPrerequisites <- getProcessStepsPrerequisites(stepIds)
processStepsPrerequisiteProcessTemplate <- getProcessStepsPrerequisiteProcessTemplate(stepIds)
processTemplatesForStepPrerequisites <- getProcessTemplateForStepPrerequisite(stepIds)
// Step post conditions
processStepsPostConditions <- getProcessStepsPostConditions(stepIds)
processStepPostConditionProcessTemplate <- getProcessStepPostConditionProcessTemplate(stepIds)
processTemplatesForStepPostConditions <- getProcessTemplateForStepPostCondition(stepIds)
// Derived processes
derivedProcesses <- getDerivedProcesses(stepIds)
processTemplatesForStepDerivedProcesses <- getProcessStepsDerivedProcesses(stepIds)
// Process to process step
processStepsTemplates_ProcessTemplates <- getProcessStepsTemplates_ProcessTemplates(stepIds)
processTemplatesForProcessTemplatesToProcessStep <- getProcessTemplateToProcessStepId(stepIds)
responsible <- raciProcessTemplateDTO.getResponsibleProcessTemplates(processTemplateId) // get all responsibles for this process template
accountable <- raciProcessTemplateDTO.getAccountableProcessTemplates(processTemplateId) // get all accountables for this process template
consulted <- raciProcessTemplateDTO.getConsultedProcessTemplates(processTemplateId) // get all consulted for this process template
informed <- raciProcessTemplateDTO.getInformedProcessTemplates(processTemplateId) // get all consulted for this process template
} yield (allApprovedProcessTemplates, processTemplate, prerequisites, postConditions, processSteps, processStepsPrerequisites,
processStepsPrerequisiteProcessTemplate, processTemplatesForStepPrerequisites, processStepsPostConditions, processStepPostConditionProcessTemplate, processTemplatesForStepPostConditions, derivedProcesses,
processTemplatesForStepDerivedProcesses, processStepsTemplates_ProcessTemplates, processTemplatesForProcessTemplatesToProcessStep, approvedProcessTemplate, trainedProcessTemplate, responsible, accountable, consulted, informed)
process.map({ case (allApprovedProcessTemplates, processTemplate, prerequisites, postConditions, processSteps, processStepsPrerequisites,
processStepsPrerequisiteProcessTemplate, processTemplatesForStepPrerequisites, processStepsPostConditions, processStepPostConditionProcessTemplate, processTemplatesForStepPostConditions, derivedProcesses,
processTemplatesForStepDerivedProcesses, processStepsTemplates_ProcessTemplates, processTemplatesForProcessTemplatesToProcessStep, approvedProcessTemplate, trainedProcessTemplate, responsible, accountable, consulted, informed) =>
val sequenced = Future.sequence {
processSteps.map { step =>
val prerequisiteFuture = processStepPrerequisitesDTO.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
}
}
sequenced.map { items => {
println(items)}
}
Ok(Json.obj(
"allApprovedProcessTemplates" -> allApprovedProcessTemplates,
"processTemplate" -> processTemplate,
"prerequisites" -> prerequisites,
"postConditions" -> postConditions,
"approvedProcessTemplate" -> approvedProcessTemplate,
"trainedProcessTemplate" -> trainedProcessTemplate,
// Step prerequisites
"processStepsPrerequisites" -> processStepsPrerequisites,
"processStepsPrerequisiteProcessTemplate" -> processStepsPrerequisiteProcessTemplate,
"processTemplatesForStepPrerequisites" -> processTemplatesForStepPrerequisites,
// Step post conditions
"processStepsPostConditions" -> processStepsPostConditions,
"processStepPostConditionProcessTemplate" -> processStepPostConditionProcessTemplate,
"processTemplatesForStepPostConditions" -> processTemplatesForStepPostConditions,
// Derived processes
"derivedProcesses" -> derivedProcesses,
"processTemplatesForStepDerivedProcesses" -> processTemplatesForStepDerivedProcesses,
// Process to process step
"processStepsTemplates_ProcessTemplates" -> processStepsTemplates_ProcessTemplates,
"processTemplatesForProcessTemplatesToProcessStep" -> processTemplatesForProcessTemplatesToProcessStep,
"steps" -> processSteps,
"responsible" -> responsible,
"accountable" -> accountable,
"consulted" -> consulted,
"informed" -> informed
))
})
}
你能试试这个吗:
val sequenced = Future.sequence {
processSteps.map { step =>
val prerequisiteFuture = processStepPrerequisitesDTO.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
})
}
}
sequenced.map { items =>
items foreach (println("diddled", _.prerequisites))
}
?
------------------------------------更新------ ------------------
您没有提供任何关于此代码位置真正 运行 的上下文。因此,如果您希望它最终打印在控制台中,您需要确保主线程或任何线程当序列中的所有期货都完成时,还有 运行 吗? 这是一个简化的例子: 导入 scala.concurrent.Future 导入 scala.concurrent.ExecutionContext.Implicits.global
object Test {
def main(args:Array[String]):Unit = {
val sequence = Seq(Future({Thread.sleep(100); 1}), Future({Thread.sleep(200); 2}))
val sequenced = Future.sequence(sequence)
sequenced foreach(items => items foreach(println(_)))
Thread.sleep(1000)
}
}
产生以下控制台输出:
1
2
Process finished with exit code 0
但在此示例中使用 Thread.sleep
或 Await
仅用于在控制台中显示结果。
您最初的问题是您将期货序列包装到 Future.sequence
中,但之后您仍然尝试使用内部序列,您从未使用过 Future.sequence
未来实例创建的。
我认为在你的代码中你将结果 future 传递给了更高的上下文,所以你需要检查并 println
那里是否是这样的,例如网络应用程序。
如果考虑到以上所有内容,它仍然打印空向量 - 那么这意味着该向量确实是空的,因此您需要在本地调试并找出原因。
您需要了解的几件事:
如果函数中没有return语句,则function/lambda的return类型由函数的最后一条语句定义。 所以函数
prerequisiteFuture.map(prereqs => { step.prerequisites = Some(prereqs) println("COPY", step.prerequisites) })
将 return 未来 [Unit],因为 return 类型的 println() 是 Unit。
Future.sequence 将
List[Future[A]]
转换为Future[List[A]]
。
因此,在上面的示例中,您创建了一个将打印但不会 return 任何内容的未来。 稍后您只需打印步骤。
由于 future 被延迟,输出将是 diddled
后跟 COPY
。
如果你想在 Copy 之后执行 diddled 你应该使用 future.map()
。像这样
Future.sequence {processSteps.map {
step =>
val prerequisiteFuture = processStepPrerequisitesDTO
.getProcessStepPrerequisiteIdsByProcessTemplateIdSeq(step.id.get)
prerequisiteFuture.map(prereqs => {
step.prerequisites = Some(prereqs)
println("COPY", step.prerequisites)
step.prerequisites
})
}
}.map {
items =>
items.map { step =>
println("diddled", step.prerequisites)
}
Ok("your json response here")
}