Async let 是Swift并發框架的一部分,允許異步實例化一個常量。并發框架引入了async-await的概念,這使得異步方法的并發性結構化,代碼更易讀。
如果你是第一次接觸async-await,建議先閱讀我的文章Swift 中的async/await ——代碼實例詳解。
如何使用 async let
在解釋如何使用 async let
時,了解何時使用 async let
更為重要。我將向您介紹使用異步方法加載隨機圖像的代碼示例:
func loadImage(index: Int) async -> UIImage {
let imageURL = URL(string: "https://picsum.photos/200/300")!
let request = URLRequest(url: imageURL)
let (data, _) = try! await URLSession.shared.data(for: request, delegate: nil)
print("Finished loading image \(index)")
return UIImage(data: data)!
}
如果沒有 async let
,我們將按如下方式調用此方法:
func loadImages() {
Task {
let firstImage = await loadImage(index: 1)
let secondImage = await loadImage(index: 2)
let thirdImage = await loadImage(index: 3)
let images = [firstImage, secondImage, thirdImage]
}
}
通過這種方式,我們告訴我們的應用程序等待第一個圖像被返回,直到它可以繼續獲取第二個圖像。所有圖像都按順序加載,我們將永遠在控制臺中看到以下順序打印出來:
Finished loading image 1
Finished loading image 2
Finished loading image 3
起初,這可能看起來很好。我們的圖片是異步加載的,我們最終得到了一個圖片數組,我們可以用它來在視圖中顯示。然而,并行加載圖像,并從可用的系統資源中獲益,會有更高的性能。
這就是async let
的用武之地:
func loadImages() {
Task {
async let firstImage = loadImage(index: 1)
async let secondImage = loadImage(index: 2)
async let thirdImage = loadImage(index: 3)
let images = await [firstImage, secondImage, thirdImage]
}
}
有幾個重要的部分需要指出:
- 我們的圖像數組現在需要使用
await
關鍵字來定義,因為我們正在處理異步常量 - 一旦我們定義了
async let
方法就會開始執行
最后一點基本上意味著,其中一張圖片在數組中被等待之前就已經被你的應用程序下載了。在這種情況下,這只是理論上的,因為你的代碼執行的速度很可能比圖片的下載速度快。
運行此代碼將在控制臺中顯示不同的輸出:
Finished loading image 3
Finished loading image 1
Finished loading image 2
每次你運行應用程序時,它可能是不同的,因為順序取決于下載圖像所需的請求時間。
什么時候使用 async let?
當你在代碼的后期才需要異步方法的結果時,應該使用async let
。如果你的代碼中的任何后續行都依賴于異步方法的結果,你應該使用await
來代替。
我可以在頂層聲明 async let 嗎?
您可能想知道以下代碼在 Swift 中是否有效:
final class ContentViewModel: ObservableObject {
async let firstImage = await loadImage(index: 1)
// .. rest of your code
}
不幸的是,編譯器會顯示錯誤:
async let 不能在頂級聲明中使用。
換句話說,您只能在方法內的本地聲明上使用 async let
。
繼續您的 Swift 并發之旅
并發更改不僅僅是 async-await,還包括許多您可以在代碼中受益的新功能。所以當你在做的時候,為什么不深入研究其他并發特性呢?
- Swift 中的 async/await
- Swift 中的 async let
- Swift 中的 Task
- Swift 中的 Actors 使用以如何及防止數據競爭
- Swift 中的 MainActor 使用和主線程調度
- 理解 Swift Actor 隔離關鍵字:nonisolated 和 isolated
- Swift 中的 Sendable 和 @Sendable 閉包
- Swift 中的 AsyncThrowingStream 和 AsyncStream
- Swift 中的 AsyncSequence
結論
Async let 允許我們組合多個異步調用并一次等待所有結果。這是一種利用可用系統資源并行下載的好方法,同時在所有異步請求完成后仍然組合結果。結合 async-await 和 actor,它們形成了一種在 Swift 中處理并發的強大的新方法。