【问题标题】:Execution order in Scala for/yield blockScala for/yield 块中的执行顺序
【发布时间】:2016-02-12 10:36:15
【问题描述】:

我使用以下语法进行了三个数据库调用(均返回 Future 值):

for {
  a <- databaseCallA
  b <- databaseCallB(a)
  c <- databaseCallC(a)
} yield (a,b,c)

第二个和第三个调用取决于第一个调用的结果,但它们两个可以并行运行。

如何在databaseCallB 之后立即发出databaseCallC(无需等待结果b)?

或者这已经发生了?

【问题讨论】:

    标签: scala concurrency future yield


    【解决方案1】:

    目前没有发生这种情况 - 您已经告诉 Futures 一个接一个地开始。要并行化第二次和第三次调用,您可以使用以下命令:

    for {
      a <- databaseCallA
      (eventualB, eventualC) = (databaseCallB(a), databaseCallC(a))
      b <- eventualB
      c <- eventualC
    } yield(a,b,c)
    

    这将在 a 可用时立即开始 b 和 c 的计算,并在所有三个都可用时完成。

    【讨论】:

    • 我认为需要额外的带有最终结果的行?没有直接(b,c) &lt;- (callB, callC)
    • 这是必需的,因为表达式(callB, callC)Tuple2[Future, Future] 类型的,你的理解将无法处理它
    • 我想知道这里可以使用sequence吗?它可能没有这个解决方案那么优雅,但可能更通用。
    • 您当然可以使用 aAndB &lt;- Future.sequence(Seq(dbCallB(a), dbCallC(a))) 之类的东西 - 但您需要再次分解序列,这只是添加符号。
    • @VictorMoroz 您可以在一行中提取序列for { Seq(a, b) &lt;- Future.sequence(Seq(dbCallB(a), dbCallC(a))) } 。请注意,如果 dbCallBdbCallC 具有不相关的返回类型,它可能会丢失类型。在这种情况下,您必须手动重新键入它们,例如for { Seq(a: Int, b: String) &lt;- ...
    猜你喜欢
    • 2021-09-30
    • 2014-05-10
    • 1970-01-01
    • 2017-01-02
    • 2021-07-08
    • 1970-01-01
    • 2015-03-26
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多