Maximize Server Throughput with Scala Futures
blog.naytev.com
blog.naytev.com
1) I want this, get started 2) I'll check when I need this, then I'll wait
This is what I do when I want to order pizza for pickup and it's easier to debug most of the time - they're only annoying when the pizzas ordered were never picked up (& you get a memory leak, eventually).
Basically what he means with that code is: Do four things in parallel and then return the result. What his code ACTUALLY does is do 4 things in sequence in a non-blocking way. This isn't bad (certainly better than blocking for each step) but it misses the real value. He should fire the for futures and then use traverse or Future.sequence to combine them. It is uglier but actually achieves the intended result.
For comprehensions reduce a lot of syntactic noise and are good to have although you need to make sure that you spawn futures outside of it.
val future1 = asyncService1()
val future2 = asyncService2()
val future3 = asyncService3()
val future4 = asyncService4()
val resultFuture:Future = for { //For-comprehension
r1 <- future1
r2 <- future2
r3 <- future3
r4 <- future4
} yield (someOperation(r1, r2, r3, r4))
looks a lot like this val resultFuture:Future = for { //For-comprehension
r1 <- asyncService1()
r2 <- asyncService2()
r3 <- asyncService3()
r4 <- asyncService4()
} yield (someOperation(r1, r2, r3, r4))
But the second one will be sequential. This is a common trap for new Scala futures users. You are right (as is the op below) that the first one work the way you expect. It is just easy for new users who don't understand how the de-sugaring resolves for get "caught."