async/await Fundamentals
33.1 Async Functions
await marks suspension points. The function may pause and resume (possibly on a different thread). Code reads sequentially, without callback pyramids.
func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, response) = try await URLSession.shared.data(from: url)
guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw URLError(.badServerResponse) }
return try JSONDecoder().decode(User.self, from: data)
}
func loadProfile() async {
do {
let user = try await fetchUser(id: 1) // suspension point: the thread is freed while waiting
print(user.name)
} catch {
print("Failed: \(error)")
}
}33.2 Calling Async Code
// From synchronous code: create a Task
Task {
await loadProfile()
}
// Async entry point
@main
struct App {
static func main() async throws {
let user = try await fetchUser(id: 1)
print(user)
}
}
// SwiftUI: .task modifier (cancelled automatically when the view disappears)
// Text(name).task { name = await loadName() }33.3 Async Properties, Sequences and Concurrent Bindings
struct Photo {
var thumbnail: Data {
get async throws { try await download("thumb") } // async computed property
}
}
async let first = fetchUser(id: 1) // start concurrently
async let second = fetchUser(id: 2)
let users = try await [first, second] // await both
for try await line in URL(fileURLWithPath: "log.txt").lines { // AsyncSequence
print(line)
}