Reputation: 20242
If I have the following for comprehension, futures will be executed in order: f1
, f2
, f3
:
val f = for {
r1 <- f1
r2 <- f2(r1)
r3 <- f3(r2)
} yield r3
For this one however, all the futures are started at the same time:
val f = for {
r1 <- f1
r2 <- f2
r3 <- f3
} yield ...
How can I enforce the order?(I want this order of execution f1
, f2
, f3
)
Upvotes: 1
Views: 1954
Reputation: 40508
It does matter what f1
, f2
, f3
are: a future will start executing a soon as it is created. In your first case, f2(r1)
must be a function returning a future, so the future begins executing when the function is called, which happens when r1
becomes available.
If the second case is the same (f2
is a function), then behavior will be the same as the first case, your futures will be executed sequentially, one after the other.
But if you create the futures outside the for
, and just assign them to variables f1
, f2
, f3
, then by the time you get inside the comprehension, they are already running.
Upvotes: 3
Reputation: 1876
Executing futures in for comprehension is default behavior. It is good when few tasks are processed parrallel without any blocking.
But if you want to preserve procecessing order you have to ways:
use andThen
operator
val allposts = mutable.Set[String]()
Future {
session.getRecentPosts
} andThen {
posts => allposts ++= posts
} andThen {
posts =>
clearAll()
for (post <- allposts) render(post)
}
Upvotes: 2
Reputation: 35990
Future
are eager constructs, that is, once created you can not dictate when they get processed. If the Future
already exists when you attempt to use it in a for-comprehension, you've already lost the ability to sequence it's execution order.
If you want to enforce ordering on a method that accepts Future
arguments then you'll need to wrap the evaluation in a thunk:
def foo(ft: => Future[Thing], f2: => Future[Thing]): Future[Other] = for{
r1 <- ft
r2 <- f2
} yield something(r1, r2)
If, on the other hand, you want to define the Future
within a method body, then instead of val
use a def
def foo() ={
def f1 = Future{ code here... }
def f2 = Future{ code here... }
for{
r1 <- f1
r2 <- f2
} yield something(r1, r2)
Upvotes: 2