`Task.await/2` and `Task.await_many/2`

1 minute read

Introduction

These days, I received a requirement to call several APIs simultaneously. It's common sense to use Task for this purpose, and I naturally gravitated towards using it. However, I came across Task.yield/2 and wondered about the difference between it and Task.await. Let's explore this.

Look some code snippets

1for ms <- [2_000, 4_000, 6000] do
2  Task.async(fn -> Process.sleep(ms); ms end)
3end
4|> Enum.map(&Task.await(&1, 3000))
5
6# return [2000, 4000, 6000]
1for ms <- [2_000, 4_000, 6_000] do
2  Task.async(fn -> Process.sleep(ms); ms end)
3end
4|> Task.yield_many(3000)
5
6# return ** (EXIT) time out

Summary

If you use await in Enum.map/2, each await picks up after the previous one finishes with a fresh 3-second timeout. Since each task blocks for 2 seconds before finishing, no timeout is triggered, but the total runtime exceeds the expected duration.