Reading — step 1 of 5
Learn
~1 min readTasks, ETS, Macros
For one-off async work, Task is simpler than full GenServer. Like Promise/Future but using Elixir's process model.
task = Task.async(fn ->
Process.sleep(100)
:computation_result
end)
# Other work happens here, in parallel
result = Task.await(task, 5_000) # block up to 5s
Parallel execution:
tasks = Enum.map(urls, fn url ->
Task.async(fn -> fetch(url) end)
end)
results = Enum.map(tasks, &Task.await(&1, 30_000))
Task.async_stream — better for many tasks; controls concurrency:
urls
|> Task.async_stream(&fetch/1, max_concurrency: 4, timeout: 30_000)
|> Enum.to_list()
# [{:ok, result1}, {:ok, result2}, ...]
max_concurrency caps how many Tasks run at once. Useful for rate limiting.
Task.Supervisor — supervised tasks (recommended for production):
# In your supervision tree:
children = [
{Task.Supervisor, name: MyApp.TaskSup}
]
# Then:
Task.Supervisor.async_nolink(MyApp.TaskSup, fn -> ... end)
async_nolink is like async but the calling process won't crash if the task does — error becomes a message you can match on.
Task.start — fire-and-forget, no result expected:
Task.start(fn -> log_event(event) end)
Differences from GenServer:
- Task: one-shot computation
- GenServer: long-lived stateful server
Most concurrent code in Elixir uses Task for parallel work + GenServer for state.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…