首页 文章

playframework scala如何等待asyncronousity

提问于
浏览
0

再次,我对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.sequence更快 .

我不想用Await ......

谢谢 .

UPDATE

这是我的完整控制器函数: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
  ))
})
}

2 回答

  • 1

    您需要了解的几件事情:

    • 函数/ lambda的返回类型由函数的最后一个语句定义,如果函数中没有return语句 . 所以功能

    prerequisiteFuture.map(prereqs => { step.prerequisites = Some(prereqs) println("COPY", step.prerequisites) })

    将返回Future [Unit],因为println()的返回类型是Unit .

    • Future.sequence将 List[Future[A]] 转换为 Future[List[A]] .

    因此,在上面的示例中,您创建了一个将打印但不会返回任何内容的未来 . 后来你只是打印这些步骤 .

    由于未来会延迟,因此输出将为 diddled ,然后是 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")
        }
    
  • 1

    你能试一试吗:

    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))
    }
    

    ------------------------------------- UPDATE ------------ -------------

    你没有提供关于这个代码所在位置的任何上下文 . 所以如果你想让它最终在控制台中打印,你需要确保你所拥有的主线程或任何线程仍在运行时序列完成 . 这是一个简化的例子:import scala.concurrent.Future import 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.sleepAwait 才能在控制台中显示结果 . 你最初的问题是你把期货的seq包装成了 Future.sequence 但是之后你仍然试图使用内部seq,你从未使用 Future.sequence 未来的实例创建 .

    我认为在您的代码中,您将生成的未来传递给更高的上下文,因此您需要检查和 println ,如果这是例如网络应用程序 .

    如果考虑到上面的所有内容,它仍会打印空向量 - 那么这意味着向量确实是空的,因此您需要在本地调试并找出原因 .

相关问题