简体   繁体   English

Scala中序列中的多个期货

[英]Multiple Futures in a Sequence in Scala

I have two computations that happen in a Future as below: 我在Future中有两个计算,如下所示:

val comp1 = Future { ... }
val comp2 = Future { ... }

I want this to run such that comp2 always runs after comp1 has completed! 我想要这样运行comp2总是在comp1完成后运行! I know that using a for expression, I can compose these two Future's like. 我知道使用for表达式,我可以将这两个Future组合起来。

for {
  comp1Result <- comp1
  comp2Result <- comp2
} yield { ... }

What could be the guarantee that comp1 is completed before comp2? 什么可以保证comp1在comp2之前完成? I mean these are computations that happen in a different thread and there is no guarantee to the order in which this might be run. 我的意思是这些是在不同的线程中发生的计算,并且不能保证可以运行它的顺序。 Is there a way to guarantee order without blocking? 有没有办法保证订单不受阻塞?

Scala for comprehensions are syntactic sugar for combinations of flatMap and map calls on the 'container type' (Futures, in this case), so your code above equates to: 用于理解的Scala是针对“容器类型”(在本例中为Futures)的flatMap和map调用的组合的语法糖,因此上面的代码等同于:

comp1.flatMap{ comp1Result => comp2 }

the computation inside the curly braces here occurs only after comp1 completes and returns a successful result (in the case of failure, the internal computation doesn't get executed). 此处花括号内的计算仅在comp1完成后才会发生并返回成功结果(在失败的情况下,内部计算不会被执行)。

If you define comp2 outside of the for comprehension as shown in the question, you are kicking off that computation then (you just ignore the outcome until you're inside the for comprehension), but if you define it only inside the for comprehension, then it won't be kicked off unless and until comp1 completes successfully. 如果你在问题之外定义comp2之外的comp2,那么你就开始计算(你只是忽略了结果,直到你进入for comprehension),但是如果你只在for comprehension中定义它,那么除非并且直到comp1成功完成,否则它不会被启动。 So, try rejigging the code as follows: 因此,请尝试按如下方式重新编写代码:

val comp1 = Future { ... } // or you could put this construction inside the for as well
for {
  comp1Result <- comp1
  comp2Result <- Future { ... } // Only start the computation here
  comp3Result <- Future { ... } // etc. for as many such computations as you need
} yield { ... }

Other alternatives are to declare comp2 as a lazy val (so it isn't actually evaluated - kicking off the computation - until it is referenced), or as a lambda (eg val comp2 = () => Future { ... } ) and call it with the line 其他替代方法是将comp2声明为惰性val(因此它实际上没有被计算 - 开始计算 - 直到它被引用),或者作为lambda(例如val comp2 = () => Future { ... } )并用线路调用它

  comp2Result <- comp2()

inside the for comprehension. 在理解中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM