In Swift’s concurrency model, you can handle multiple concurrent streams of work using async let or the TaskGroup API. Both approaches allow you to perform concurrent tasks and wait for their results.
Option 1: Using async let
async let is a concise way to launch multiple tasks concurrently and wait for their results.
func fetchData() async throws -> (String, Int, Bool) { async let stringResult = doSomethingAsync() async let intResult = somethingElseAsync() async let boolResult = thirdThingAsync()
// Wait for all tasks to complete
return try await (stringResult, intResult, boolResult)
}
Here: • Each async let runs concurrently. • try await gathers their results. If any task throws, the error is propagated.
Option 2: Using TaskGroup
TaskGroup offers more flexibility, especially if the number of tasks is dynamic or the results need to be processed as they complete.
func fetchData() async throws -> [Any] { try await withThrowingTaskGroup(of: Any.self) { group in group.addTask { try await doSomethingAsync() } group.addTask { try await somethingElseAsync() } group.addTask { try await thirdThingAsync() }
var results: [Any] = []
for try await result in group {
results.append(result)
}
return results
}
}
Here: • withThrowingTaskGroup manages the tasks in the group. • Results are processed as each task completes. • If a task throws, the error is propagated, and other tasks may be canceled.
Option 3: Fire-and-Forget Tasks
If you don’t need the results immediately (or at all), you can use detached tasks or Task.
Task {
async let _ = doSomethingAsync()
async let _ = somethingElseAsync()
async let _ = thirdThingAsync()
// No need to await
, tasks will run concurrently
}
Key Points: 1. Error Handling: • async let and TaskGroup propagate errors if any task fails. • Fire-and-forget tasks don’t handle errors unless explicitly managed. 2. Concurrency Control: • Tasks launched with async let or TaskGroup run in parallel but respect structured concurrency. 3. TaskGroup for Dynamic Work: • Use TaskGroup if the number of tasks isn’t fixed or results need to be processed dynamically.
Choose the method based on the complexity and requirements of your use case.