将内容添加到序列的scala计时问题

将内容添加到序列的scala计时问题,scala,playframework,Scala,Playframework,我有一个问题涉及scala中的范围界定。我有这样一个函数: def getElements(id: Int): Seq[Element] = { var test = "" dto.getElementIds(id).map { elementIds => { test += " hello " elementIds.foreach(elementId => dto.getElement(elementId).map {

我有一个问题涉及scala中的范围界定。我有这样一个函数:

def getElements(id: Int): Seq[Element] = {
    var test = ""
    dto.getElementIds(id).map {
      elementIds => {
        test += " hello "
        elementIds.foreach(elementId => dto.getElement(elementId).map {
          case Some(element) => test += " hi "
                println("ThirdPrint: " + test)
        })
        println("SecondPrint: " + test)
      }
    }
    println("FirstPrint: " + test)
}
假设“elementsIds”的长度为2。 控制台显示: 首次打印: 你好 第三点:你好 第三点:你好 scala为什么要这么做?我假设第三次打印首先执行。当我看到第一张照片时,“嗨”已经不见了。为什么最后一行代码先执行? 我和斯里克和期货公司合作,这和它有关系吗?谢谢

更新

谢谢,很好用。 是否可以返回一个seq?像这样:

 def getElements(id: Int): Future[Seq[Element]] = {
    var mySequence: Seq[Element] = Seq()
    val elementsIds: Future[Seq[Int]] = dto.getElementIds(id)
    var test = ""
    val elementsF = elementsIds.flatMap {
      elementIds => {
        test += " hello "
        val idsAsElements: Seq[Future[Element]] = elementIds.map(elementId => dto.getElement(elementId).collect {
          case Some(element) => mySequence = mySequence :+ element
        })
        val idsAsElementsF: Future[Seq[Element]] = Future.sequence(idsAsElements)
        idsAsElementsF.onComplete(_ => println("SecondPrint: " + test))
        idsAsElementsF
      }
    }
    elementsF.onComplete(_ => println("FirstPrint: " + test))
    elementsF
  }
当IDASElements为“onComplete”时,是否可以返回“mySequence”

输出:

第三点:你好

第三点:你好

第三点:你好

第二印:你好,你好

你好,你好

输出:

第三点:你好

第三点:你好

第三点:你好

第二印:你好,你好


FirstPrint:hello-hi

是的,这不是一个好的解决方案。您应该避免在代码中阻塞,除非是在可能的最高级别(
main
method)。而且,可变状态是不好的,特别是当与并发(未来)结合使用时

您的函数应该返回一个
Future
。类似的方法会起作用(我不确定我是否正确地猜测了代码的意图-您的函数声明为返回
Seq[Element]
,但编写为返回
单元
…我假设,您真正想要返回的是对每个id调用
getElement
的结果):

我删除了您的打印输出,因为我不确定它们的用途(因为对dto.getElement的调用也是并行进行的,所以不清楚您希望将这些字符串打印在何处以及打印顺序)

您可以通过在末尾添加另一个转换来模拟“预期输出”,例如:

  .andThen { case Success(results) => 
     val str = results.foldLeft("hello") { case (a,b) => 
        println("ThirdPrint: " + a + " hi")
        a + " hi"
     }
     println("SecondPrint: " + str)
     println("FirstPrint: " + str
  }

是的,这不是一个好的解决方案。您应该避免在代码中阻塞,除非是在可能的最高级别(
main
method)。而且,可变状态是不好的,特别是当与并发(未来)结合使用时

您的函数应该返回一个
Future
。类似的方法会起作用(我不确定我是否正确地猜测了代码的意图-您的函数声明为返回
Seq[Element]
,但编写为返回
单元
…我假设,您真正想要返回的是对每个id调用
getElement
的结果):

我删除了您的打印输出,因为我不确定它们的用途(因为对dto.getElement的调用也是并行进行的,所以不清楚您希望将这些字符串打印在何处以及打印顺序)

您可以通过在末尾添加另一个转换来模拟“预期输出”,例如:

  .andThen { case Success(results) => 
     val str = results.foldLeft("hello") { case (a,b) => 
        println("ThirdPrint: " + a + " hi")
        a + " hi"
     }
     println("SecondPrint: " + str)
     println("FirstPrint: " + str
  }

dto.getElementIds(id)
是否返回一个
Future
?你能提供类型吗?是的,未来[Seq[Int]](id),所以它在后台并行线程中运行。当您的
FirstPrint
在行中执行时,另一个线程仍在从它获取ID的位置获取这些ID,一旦发生这种情况,就会执行
.map
。好的,我如何解决这个问题?解决什么?这是预期的行为。您希望发生什么?是
dto.getElementIds(id)
返回一个
Future
?你能提供类型吗?是的,未来[Seq[Int]](id),所以它在后台并行线程中运行。当您的
FirstPrint
在行中执行时,另一个线程仍在从它获取ID的位置获取这些ID,一旦发生这种情况,就会执行
.map
。好的,我如何解决这个问题?解决什么?这是预期的行为。您希望发生什么?如果使用。请不要忘记。map您必须覆盖所有情况。map{case Some(a)=>…}在none上失败您希望从函数接收第一个完成的idsalements并跳过其他项吗?我希望附加返回值(Some(element))如下所示:
mySequence=mySequence:+element
from
val-idsalements:Seq[Future[element]]=elementIds.map(elementId=>dto.getElement(elementId)。收集{…}
并在列表完成后返回该列表。如果需要“完成后的列表”,您可以执行wait.result(elementsF,duration)在上面的代码中。但是这是一个坏主意,这个函数必须返回Future,否则会阻塞主线程。如果使用var是一个瓶颈,并且需要提高性能,那么使用var只有一个原因。使用Await.result有两个原因。第一个是调试代码,第二个是单元测试。没有其他方法替代吗ad of await?如果您使用,请不要忘记。map您必须覆盖所有情况。map{case Some(a)=>…}在none上失败您想从函数接收第一个完成的idsalements并跳过其他吗?我想附加返回值(Some(element)),如下所示:
mySequence=mySequence:+element
from
val idsalements:Seq[Future[Element]]=elementId.map(elementId=>dto.getElement(elementId)。收集{…}
并在列表完成后返回该列表。如果需要“完成后的列表”,可以执行Wait.result(elementsF,duration)在上面的代码中。但是这是一个坏主意,这个函数必须返回Future,否则会阻塞主线程。如果使用var是一个瓶颈,并且需要提高性能,那么使用var只有一个原因。使用Await.result有两个原因。第一个是调试代码,第二个是单元测试。没有其他方法替代吗等待的广告?
  .andThen { case Success(results) => 
     val str = results.foldLeft("hello") { case (a,b) => 
        println("ThirdPrint: " + a + " hi")
        a + " hi"
     }
     println("SecondPrint: " + str)
     println("FirstPrint: " + str
  }