When I make a future
, or apply methods like onSuccess
and map
, I can specify ExecutionContext for them.
For example,
val f = future {
// code
} executionContext
f.map(someFunction)(executionContext)
f onSuccess {
// code
} executionContext
However, if I use a for-comprehension of future, how can I specify ExecutionContext for the yield
part?
for {
f <- future1
g <- future2
} yield {
// code to be executed after future1 onSuccess and future2 onSuccess
// What ExecutionContext runs this code?
} // (executionContext) here does not work
And, what ExecutionContext runs the code in yield if not specified?
OK. Thanks to answers, I found something.
If I don't define or import implicit ExecutionContext (like Implicits.global
),
the for-comprehension does not compile. That means, for-comprehension uses implicit ExecutionContext.
Then, how can I use for-comprehension without implicit ExecutionContext, i.e. how to specify?
Future represents a result of an asynchronous computation that may or may not be available yet. When we create a new Future, Scala spawns a new thread and executes its code. Once the execution is finished, the result of the computation (value or exception) will be assigned to the Future.
An ExecutionContext can execute program logic asynchronously, typically but not necessarily on a thread pool. A general purpose ExecutionContext must be asynchronous in executing any Runnable that is passed into its execute -method.
A Future is a placeholder object for a value that may not yet exist. Generally, the value of the Future is supplied concurrently and can subsequently be used. Composing concurrent tasks in this way tends to result in faster, asynchronous, non-blocking parallel code.
sequence takes a list of futures and transforms it into a single future of list in an asynchronous manner. For instance, assume that you have a list of independent jobs to be run simultaneously. In such a case, the list of futures can be composed into a single future of list using Future.
Similarly to the Java Executor the Scala ExecutionContext allows to separate the business logic (i.e. what the code does) from the execution logic (i.e. how the code is executed). As a consequence one cannot just import the global execution context and get away with that. Instead we need to understand which execution context is needed and why.
By Alvin Alexander. Last updated: August 16, 2022 If you want to create multiple Scala Futures and merge their results together to get a result in a for comprehension, the correct approach is to (a) first create the futures, (b) merge their results in a for comprehension, then (c) extract the result using onComplete or a similar technique.
For Comprehensions. Scala offers a lightweight notation for expressing sequence comprehensions. Comprehensions have the form for (enumerators) yield e, where enumerators refers to a semicolon-separated list of enumerators. An enumerator is either a generator which introduces new variables, or it is a filter.
The Scala programming language introduced a new kind of loop: the for-comprehension. Like many other Scala constructs, the for-comprehension comes directly from Haskell. Its use goes far beyond simply looping over collections, helping us to deal with the complexity of the syntax when using a functional approach to programming.
The ExecutionContext
parameter is actually implicit
. That means you can:
import scala.concurrent.ExecutionContext
implicit val context = ExecutionContext.fromExecutor(//etc)
for {
f <- future1
g <- future2
} yield {
// code to be executed after future1 onSuccess and future2 onSuccess
// What ExecutionContext runs this code?: the one above.
}
You also have a default, namely scala.concurrent.ExecutionContext.Implicits.global
.
This has as many threads as the processors on the running machine.
It won't be used by all Futures by default, you still have to import it.
Update: If you really want to specifiy, although it's not recommended, you can unwrap the for yield
val combined = futureA.flatMap(x => futureB)(context)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With