【问题标题】:playframework scala how to wait for asyncronousityplayframework scala如何等待异步
【发布时间】:2018-02-23 10:33:01
【问题描述】:

我再次遇到了 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
  ))
})
}

【问题讨论】:

  • processSteps 的类型是什么?
  • 撰写,而不是等待异步(使其同步等等..)

标签: scala playframework playframework-2.0


【解决方案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))
}

?

--------------------------更新--------- ----------------

您没有提供有关此代码实际运行位置的任何上下文。因此,如果您希望它最终在控制台中打印,您确实需要确保主线程或您拥有的任何线程仍在运行时序列中的所有期货都已完成。 这是一个简化的示例: 导入 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.sleepAwait 仅用于在控制台中显示结果。 您最初的问题是您将期货的 seq 包装到 Future.sequence 但之后您仍然尝试使用内部 seq,您从未使用过由 Future.sequence 创建的未来实例。

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

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

【讨论】:

  • 我在_.prerequisites旁边收到了这条消息missing parameter type for expanded function ((x$12) =&gt; x$12.prerequisites)
  • 当我这样做时sequenced.map { items =&gt; { println(items)} } 打印一个空的 Vector((),())
  • 我已经更新了我的答案。您还没有使用Future.sequence 申请结果。这是主要问题。其余的我无法为您解决,因为我不知道这段代码在哪里运行以及您将结果传递到哪里。简化示例向您展示了 Future.seqence 用法的正确语义。
  • 我已经在上面添加了整个控制器功能
  • Felix,sequenced 现在也是未来。因此,如果您想在Ok(Json.obj(.... 中使用它,您需要以适当的方式进行操作。你还需要写像sequenced.map(result =&gt; Ok(Json.obj(....)))这样的东西,同样,在Json中你需要使用result而不是processSteps
【解决方案2】:

你需要了解的几件事:

  1. 如果函数中没有返回语句,则函数/lambda 的返回类型由函数的最后一条语句定义。 所以函数

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

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

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

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

由于未来延迟,输出将是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")
    }

【讨论】:

  • 当我这样做时,我得到了found : play.api.mvc.Result required: scala.concurrent.Future[?]
  • 我的错误应该是地图而不是 flatMap。
  • 抱歉无法编译。 overloaded method value async with alternatives: [error] (block: play.api.mvc.Request[play.api.mvc.AnyContent] =&gt; scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] &lt;and&gt; [error] (block: =&gt; scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] [error] cannot be applied to (scala.concurrent.Future[scala.concurrent.Future[play.api.mvc.Result]]) [error] def getEditProcessTemplateData(processTemplateId: Int): Action[AnyContent] = Action.async {
  • 而不是 Action[AnyContent] 它应该是 Action[JsValue] 因为你要返回 Json
  • 我更改了它...但出现了新错误:verloaded method value async with alternatives: [error] [A](bodyParser: play.api.mvc.BodyParser[A])(block: play.api.mvc.Request[A] =&gt; scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[A] &lt;and&gt; [error] (block: play.api.mvc.Request[play.api.mvc.AnyContent] =&gt; scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] &lt;and&gt; [error] (block: =&gt; scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] [error] cannot be applied to
猜你喜欢
  • 1970-01-01
  • 2013-12-04
  • 2013-03-28
  • 1970-01-01
  • 2023-03-12
  • 2016-07-07
  • 2016-03-25
  • 2017-10-09
相关资源
最近更新 更多