Scala 在循环中处理期货

Scala 在循环中处理期货,scala,asynchronous,concurrency,slick,slick-3.0,Scala,Asynchronous,Concurrency,Slick,Slick 3.0,我正在研究一种方法,该方法对数据库进行查询并获取一行。此行有一列指定父id(如果有)。因此,我的方法有一个名为“iterate”的闭包,如果最后一行有父行,则该闭包执行相同的过程,最后该方法返回这些行的序列。乍一看,这很简单,但我必须处理未来之类的事情,而且我对异步编程没有太多经验。所以我的问题是: 有没有一种方法可以在不使用“等待”的情况下正确使用此方法? /** * Returns all the parents of the given sector if any * @par

我正在研究一种方法,该方法对数据库进行查询并获取一行。此行有一列指定父id(如果有)。因此,我的方法有一个名为“iterate”的闭包,如果最后一行有父行,则该闭包执行相同的过程,最后该方法返回这些行的序列。乍一看,这很简单,但我必须处理未来之类的事情,而且我对异步编程没有太多经验。所以我的问题是:

有没有一种方法可以在不使用“等待”的情况下正确使用此方法?

/**
   * Returns all the parents of the given sector if any
   * @param childSector
   * @return
   */
  def getParents(childSector: ShopSector): Future[Option[Seq[ShopSector]]] = {
    val p = Promise[Option[Seq[ShopSector]]]
    val f: Future[Option[Seq[ShopSector]]] = p.future

    val parentsSeq: Seq[ShopSector] = Seq()

    f.onComplete( thing => println(s"Result from Iteration future: $thing") )

    def iterate(sector: ShopSector): Unit = {
      val query = for {
        c <- ShopSectors if c.id === sector.id
        p <- c.parent
      } yield p

      exists(sector.parent_id).map { exists =>
        if (exists) {
          db.run(query.result.head).map { parent =>
            println(s"Result parent: $parent")
            parentsSeq +: Seq(parent)
            iterate(parent)
          }
        } else {
          p success Option(parentsSeq)
        }
      }
    }

    iterate(childSector)

    f
  }
/**
*返回给定扇区的所有父级(如果有)
*@param-childSector
*@返回
*/
def getParents(childSector:ShopSector):未来[选项[Seq[ShopSector]]]={
val p=承诺[选项[序号[商店部门]]]
val f:Future[选项[Seq[ShopSector]]]=p.Future
val parentsSeq:Seq[ShopSector]=Seq()
f、 onComplete(thing=>println(s“来自未来迭代的结果:$thing”))
def迭代(扇区:商店扇区):单位={
val query=for{
C
println(s“结果父项:$parent”)
家长Seq+:序号(家长)
迭代(父级)
}
}否则{
p成功选项(parentsSeq)
}
}
}
迭代(子扇区)
F
}
顺便说一句,我用的是斯力克。请注意,这种方法效果不佳。它返回一个空的Seq,我知道很明显这会返回那个。但是打印效果很好,打印出正确的结果。问题是,我无法想象有一种方法能让一个变量在所有的未来都完成之前不“消失”

提前谢谢


编辑:好的,伙计们。问题很简单。正如Ixx所说,parentsSeq集合是不可变的。我通过使用ListBuffer,然后将其转换为序列来修复它。

我看到的一个问题是:
parentsSeq+:Seq(parent)
。这不会改变序列,而是返回一个新序列。

我看到的一个问题是:
parentsSeq+:Seq(parent)
。这不会改变序列,而是返回一个新序列。

我知道。但我认为这不是这里的主要问题。例如,我可以尝试使用ListBuffer,但问题是,如果我在clojure之外定义变量来进行异步处理,那么该变量将来就不存在了,对吗?我不确定,但我认为如果使用可变集合或变量并重新分配给它,代码会起作用。根据定义,未来是一些还不存在的东西。。。执行onComplete回调时,我认为更新的集合应该可用。这个闭包有一个对集合的引用,当未来完成时它会被更新。你是对的。问题在于收集。我一直在想这个问题是由未来造成的。无论如何。。。谢谢不客气。顺便说一句,我认为你也可以映射动作本身。因此,您可以创建一系列操作(
query.result
是一个操作),您可以递归地构建这些操作,类似于您对未来所做的操作,然后为它们创建一个单独的操作
DBIO.sequence(actions)
,并使用
db.run()
运行此操作,然后你得到一个单一的未来和一系列的结果。问题是我需要之前的结果来检查我是否需要继续查询。我知道。但我认为这不是这里的主要问题。例如,我可以尝试使用ListBuffer,但问题是,如果我在clojure之外定义变量来进行异步处理,那么该变量将来就不存在了,对吗?我不确定,但我认为如果使用可变集合或变量并重新分配给它,代码会起作用。根据定义,未来是一些还不存在的东西。。。执行onComplete回调时,我认为更新的集合应该可用。这个闭包有一个对集合的引用,当未来完成时它会被更新。你是对的。问题在于收集。我一直在想这个问题是由未来造成的。无论如何。。。谢谢不客气。顺便说一句,我认为你也可以映射动作本身。因此,您可以创建一系列操作(
query.result
是一个操作),您可以递归地构建这些操作,类似于您对未来所做的操作,然后为它们创建一个单独的操作
DBIO.sequence(actions)
,并使用
db.run()
运行此操作,然后你会得到一个带有一系列结果的未来,问题是我需要之前的结果来检查我是否需要继续查询。