async let runs a fixed number of async calls in parallel with one line each. It is syntactic
sugar over task groups, so it keeps structured concurrency's lifecycle management and
cooperative cancellation.
Sequential awaits waste time
Two awaits in a row suspend twice: the second call does not start until the first finishes.
let a = await taskA()
let b = await taskB()
print(a + b)
A task group works but is heavy
withTaskGroup runs both concurrently, at the cost of ceremony that a two-task case does not
deserve. Reserve groups for a dynamic number of tasks.
let result = await withTaskGroup(of: Int.self) { group in
group.addTask { await taskA() }
group.addTask { await taskB() }
await group.waitForAll()
return await group.reduce(0, +)
}
async let: parallel with two lines
Declare the bindings without await; both calls start immediately and run in parallel. The
await moves to the point where you read the values.
async let a = taskA()
async let b = taskB()
await print(a + b)
The child tasks are structured: they cannot outlive the enclosing scope, and cancelling the parent task cancels them.