async / await Basics
Swift Concurrency (Swift 5.5+) lets you write asynchronous code using async and await in a style that reads like synchronous code, eliminating deeply nested callbacks.
Syntax
// Define an async function
func functionName() async -> Type {
// Asynchronous work
}
// Async function that can throw errors
func functionName() async throws -> Type {
// Asynchronous work
}
// Call an async function with await
let result = await functionName()
let data = try await asyncFunctionName()
// async let: run tasks in parallel
async let a = asyncFunctionA()
async let b = asyncFunctionB()
let (resultA, resultB) = await (a, b)
Syntax Overview
| Syntax | Description |
|---|---|
| async func | Defines an asynchronous function. |
| await expression | Waits for an asynchronous function to complete. |
| async throws func | Defines an asynchronous function that can also throw errors. |
| try await expression | Calls an asynchronous function that can throw errors. |
| async let | Runs multiple asynchronous tasks in parallel. |
| Task { } | Creates a task that runs code in an asynchronous context. |
Sample Code
import Foundation
// Define an async throws function
func fetchUserName(id: Int) async throws -> String {
// In a real app, use URLSession.shared.data(from:) or similar
// Here we simulate an async operation
try await Task.sleep(nanoseconds: 100_000_000) // Wait 0.1 seconds
let users = [1: "Alice", 2: "Bob", 3: "Carol"]
guard let name = users[id] else {
throw URLError(.badURL)
}
return name
}
func fetchScore(name: String) async -> Int {
try? await Task.sleep(nanoseconds: 50_000_000)
return name.count * 10
}
// Call async functions from inside a Task
Task {
// Run sequentially
do {
let name = try await fetchUserName(id: 1)
print("Name: \(name)")
let score = await fetchScore(name: name)
print("Score: \(score)")
} catch {
print("Error: \(error)")
}
// Run in parallel with async let
async let name2 = fetchUserName(id: 2)
async let name3 = fetchUserName(id: 3)
do {
let (n2, n3) = try await (name2, name3)
print("Fetched in parallel: \(n2), \(n3)")
} catch {
print("Error: \(error)")
}
}
// Start asynchronous work from synchronous code using Task
print("Asynchronous processing started")
Notes
Using async/await from Swift Concurrency eliminates deeply nested callbacks (callback hell) and lets you write asynchronous code in a clear, linear style.
With async let, you can launch multiple asynchronous tasks in parallel and then wait for all of their results together using await. Note that await does not block the current thread — it suspends the task and releases the thread. There is no guarantee the task will resume on the same thread (use @MainActor to ensure execution returns to the main thread for UI updates).
For more on Task and TaskGroup, see Task / TaskGroup / async let.
If you find any errors or copyright issues, please contact us.