The mapAsync stage doesn't need an execution context, it only requires you to map the current stream element to a Future
. The future's execution context depends on who creates it, the flow doesn't know anything about it.
More generally, a Future[A]
is an abstraction that doesn't require you to know where it's running. It could even be a precomputed value that doesn't need an execution context:
def mappingFunction(x: Int) = Future.successful(x * 2)
Source(List(1, 2, 3)).mapAsync(1)(mappingFunction)
You only need to worry about ExecutionContexts when you create the Future, but in the case of mapAsync you're just returning one from a function. How to create the future is the function's responsibility. As far as the mapAsync stage is concerned, it just gets the future as the return value of the function, i.e. it doesn't create it.
Flows have a Materializer
. Its current implementation is the ActorMaterializer
, which materializes streams using an ActorSystem (and its dispatchers). You are not required to know the details of stream materialization though, streams work on a more abstract level and hypothetically you could have a different Materializer
that doesn't work with an ActorSystem