Swift AsyncSequence — 代碼實(shí)例詳解
前言
AsyncSequence 是并發(fā)性框架和SE-298[1] 提案的一部分。它的名字意味著它是一個(gè)提供異步、順序和迭代訪問其元素的類型。換句話說:它是我們?cè)?Swift 中熟悉的常規(guī)序列的一個(gè)異步變體。
就像你不會(huì)經(jīng)常創(chuàng)建你的自定義序列一樣,我不期望你經(jīng)常創(chuàng)建一個(gè)自定義的 AsyncSequence 實(shí)現(xiàn)。然而,由于與 AsyncThrowingStream和AsyncStream 等類型一起使用,你很可能不得不與異步序列一起工作。因此,我將指導(dǎo)你使用 AsyncSequence 實(shí)例進(jìn)行工作。
什么是 AsyncSequence?
AsyncSequence 是我們?cè)赟wift中熟悉的 Sequence 的一個(gè)異步變體。由于它的異步性,我們需要使用 await 關(guān)鍵字,因?yàn)槲覀円幚淼氖钱惒蕉x的方法。如果你沒有使用過 async/await,我鼓勵(lì)你閱讀我的文章:Swift 中的async/await ——代碼實(shí)例詳解
值可以隨著時(shí)間的推移而變得可用,這意味著一個(gè) AsyncSequence 在你第一次使用它時(shí)可能不包含也可能包含一些,或者全部的值。
重要的是要理解 AsyncSequence 只是一個(gè)協(xié)議。它定義了如何訪問值,但并不產(chǎn)生或包含值。AsyncSequence 協(xié)議的實(shí)現(xiàn)者提供了一個(gè) AsyncIterator,并負(fù)責(zé)開發(fā)和潛在地存儲(chǔ)值。
創(chuàng)建 AsyncSequence
創(chuàng)建一個(gè)自定義的 AsyncSequence。
為了更好地理解 AsyncSequence 是如何工作的,我將演示一個(gè)實(shí)現(xiàn)實(shí)例。然而,在定義你的 AsyncSequence 的自定義實(shí)現(xiàn)時(shí),你可能想用 AsyncStream 來代替,因?yàn)樗脑O(shè)置更方便。因此,這只是一個(gè)代碼例子,以更好地理解 AsyncSequence 的工作原理。
下面的例子沿用了原始提案中的例子,實(shí)現(xiàn)了一個(gè)計(jì)數(shù)器。這些值可以立即使用,所以對(duì)異步序列沒有太大的需求。然而,它確實(shí)展示了一個(gè)異步序列的基本結(jié)構(gòu):
如您所見,我們定義了一個(gè)實(shí)現(xiàn) AsyncSequence 協(xié)議的 Counter 結(jié)構(gòu)體。該協(xié)議要求我們返回一個(gè)自定義的 AsyncIterator,我們使用內(nèi)部類型解決了這個(gè)問題。我們可以決定重寫此示例以消除對(duì)內(nèi)部類型的需求:
我們現(xiàn)在可以將 self 作為迭代器返回,并保持所有邏輯的集中。
注意,我們必須通過提供 typealias 來幫助編譯器遵守 AsyncSequence 協(xié)議。
next() 方法負(fù)責(zé)對(duì)整體數(shù)值進(jìn)行迭代。我們的例子歸結(jié)為提供盡可能多的計(jì)數(shù)值,直到我們達(dá)到極限。我們通過對(duì) Task.isCancelled 的檢查來實(shí)現(xiàn)取消支持。
異步序列的迭代
現(xiàn)在我們知道了什么是 AsyncSequence 以及它是如何實(shí)現(xiàn)的,現(xiàn)在是時(shí)候開始迭代這些值了。
以上述例子為例,我們可以使用 Counter 開始迭代:
我們必須使用 await 關(guān)鍵字,因?yàn)槲覀兛赡軙?huì)異步接收數(shù)值。一旦不再有預(yù)期的值,我們就退出for循環(huán)。異步序列的實(shí)現(xiàn)者可以通過在 next() 方法中返回 nil 來表示達(dá)到極限。在我們的例子中,一旦計(jì)數(shù)器達(dá)到配置的極限,或者迭代取消,我們就會(huì)達(dá)到這個(gè)預(yù)期:
許多常規(guī)的序列操作符也可用于異步序列。其結(jié)果是,我們可以以異步的方式執(zhí)行映射和過濾等操作。
例如,我們可以只對(duì)偶數(shù)進(jìn)行過濾:
或者我們可以在迭代之前將計(jì)數(shù)映射為一個(gè) String :
我們甚至可以使用 AsyncSequence 而不使用for循環(huán),通過使用 contains 等方法。
注意,上述方法是異步的,意味著它有可能無休止地等待一個(gè)值的存在,直到底層的 AsyncSequence 完成。
結(jié)論
AsyncSequence 是我們?cè)赟wift中熟悉的常規(guī) Sequence 的異步替代品。就像你不會(huì)經(jīng)常自己創(chuàng)建一個(gè)自定義 Sequence 一樣,你也不太可能創(chuàng)建自定義的異步序列。
參考資料
[1]SE-298: https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md


























