async
和 await
是 Swift 5.5 引入的用于处理异步编程的关键字,它们使得处理异步任务变得更加简单和直观。它们提供了一种新的方式来管理异步操作,相比传统的回调函数或闭包,async
/await
更接近同步代码的写法,让代码更加易读和可维护。
1. 什么是异步编程
异步编程是指程序在执行任务时,不需要等待任务完成才能继续执行其他任务。传统的同步编程方式会导致程序等待某个操作完成(比如网络请求、磁盘读写等),直到任务完成后才会继续执行,可能会造成性能瓶颈。异步编程允许程序在等待某个操作时去执行其他任务,从而提高效率。
2. async
和 await
的基本概念
async
: 用于标记一个函数为异步函数。异步函数会返回一个Task
类型,可以在执行时暂停,直到结果准备好。await
: 用于暂停函数的执行,直到异步操作完成并返回结果。
3. 如何使用 async
和 await
3.1 标记异步函数
首先,你需要使用 async
关键字来定义一个异步函数,表示这个函数包含异步操作,并且可能需要一些时间来执行。
swift
func fetchData() async -> String {
// 模拟网络请求
return "Data fetched"
}
在上面的例子中,fetchData()
是一个异步函数,它返回一个字符串。函数内部的操作可能会是一个耗时操作,虽然这里没有具体的异步代码,但它表示这段代码可以用异步方式进行处理。
3.2 调用异步函数
要调用一个异步函数,你必须在一个异步上下文中使用 await
关键字。await
会暂停当前的代码执行,直到异步函数返回结果。
swift
func exampleUsage() async {
let result = await fetchData() // 等待异步函数返回结果
print(result)
}
3.3 异步任务的创建
你可以使用 Task
来创建异步任务。Task
允许你在异步上下文之外执行异步代码。
swift
Task {
let result = await fetchData()
print(result)
}
Task
是一个异步任务,它会自动创建一个新的异步上下文来执行异步代码。这是非常有用的,当你需要在不直接处于异步函数内部的地方执行异步代码时。
4. async
和 await
与传统的闭包回调对比
在传统的异步编程中,我们可能会使用闭包来处理异步操作的回调:
swift
func fetchData(completion: @escaping (String) -> Void) {
// 模拟网络请求
DispatchQueue.global().async {
let data = "Data fetched"
completion(data)
}
}
在上面的代码中,fetchData
接受一个回调闭包 completion
,并通过它返回结果。调用时我们需要手动处理回调:
swift
fetchData { result in
print(result)
}
而使用 async
和 await
后,你可以这样写:
swift
func fetchData() async -> String {
// 模拟网络请求
return "Data fetched"
}
Task {
let result = await fetchData()
print(result)
}
相比使用闭包,async
和 await
更加简洁、直观。
5. 错误处理
在异步函数中,错误处理通常使用 do-catch
语句来处理。你可以在异步函数中抛出错误,并使用 await
来捕获和处理它们。
swift
enum DataError: Error {
case invalidData
}
func fetchData() async throws -> String {
// 模拟可能抛出错误的网络请求
let success = false
if !success {
throw DataError.invalidData
}
return "Data fetched"
}
func exampleUsage() async {
do {
let result = try await fetchData()
print(result)
} catch {
print("Error: \(error)")
}
}
在上述代码中,fetchData()
可能会抛出 DataError.invalidData
错误,调用它时需要使用 try await
来捕获和处理错误。
6. 并发执行多个异步任务
你可以使用 async let
来并行执行多个异步任务,并且在最后获取它们的结果。这是一个非常强大的功能,尤其是当你需要同时处理多个异步操作时。
swift
func fetchData1() async -> String {
return "Data 1 fetched"
}
func fetchData2() async -> String {
return "Data 2 fetched"
}
func exampleUsage() async {
async let data1 = fetchData1() // 异步并发任务
async let data2 = fetchData2() // 异步并发任务
let result1 = await data1 // 等待结果
let result2 = await data2 // 等待结果
print(result1)
print(result2)
}
在上面的代码中,data1
和 data2
会并行执行,最终我们使用 await
来获取它们的结果。
7. 总结
async
和 await
是处理异步操作的核心工具,它们通过提供一种类似同步代码的结构,使得异步编程更加简单和清晰。使用这些特性,你可以:
- 简化代码,使其更加易读和维护。
- 避免回调地狱(callback hell)和嵌套的闭包。
- 更容易进行错误处理。
- 使并发执行变得简单,减少手动管理异步任务的复杂度。