新聞中心
前言
AsyncSequence 是并發(fā)性框架和SE-298[1] 提案的一部分。它的名字意味著它是一個提供異步、順序和迭代訪問其元素的類型。換句話說:它是我們在 Swift 中熟悉的常規(guī)序列的一個異步變體。

成都創(chuàng)新互聯(lián)公司公司2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目網(wǎng)站制作、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元橫縣做網(wǎng)站,已為上家服務(wù),為橫縣各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792
就像你不會經(jīng)常創(chuàng)建你的自定義序列一樣,我不期望你經(jīng)常創(chuàng)建一個自定義的 AsyncSequence 實現(xiàn)。然而,由于與 AsyncThrowingStream和AsyncStream 等類型一起使用,你很可能不得不與異步序列一起工作。因此,我將指導你使用 AsyncSequence 實例進行工作。
什么是 AsyncSequence?
AsyncSequence 是我們在Swift中熟悉的 Sequence 的一個異步變體。由于它的異步性,我們需要使用 await 關(guān)鍵字,因為我們要處理的是異步定義的方法。如果你沒有使用過 async/await,我鼓勵你閱讀我的文章:Swift 中的async/await ——代碼實例詳解
值可以隨著時間的推移而變得可用,這意味著一個 AsyncSequence 在你第一次使用它時可能不包含也可能包含一些,或者全部的值。
重要的是要理解 AsyncSequence 只是一個協(xié)議。它定義了如何訪問值,但并不產(chǎn)生或包含值。AsyncSequence 協(xié)議的實現(xiàn)者提供了一個 AsyncIterator,并負責開發(fā)和潛在地存儲值。
創(chuàng)建 AsyncSequence
創(chuàng)建一個自定義的 AsyncSequence。
為了更好地理解 AsyncSequence 是如何工作的,我將演示一個實現(xiàn)實例。然而,在定義你的 AsyncSequence 的自定義實現(xiàn)時,你可能想用 AsyncStream 來代替,因為它的設(shè)置更方便。因此,這只是一個代碼例子,以更好地理解 AsyncSequence 的工作原理。
下面的例子沿用了原始提案中的例子,實現(xiàn)了一個計數(shù)器。這些值可以立即使用,所以對異步序列沒有太大的需求。然而,它確實展示了一個異步序列的基本結(jié)構(gòu):
struct Counter: AsyncSequence {
typealias Element = Int
let limit: Int
struct AsyncIterator : AsyncIteratorProtocol {
let limit: Int
var current = 1
mutating func next() async -> Int? {
guard !Task.isCancelled else {
return nil
}
guard current <= limit else {
return nil
}
let result = current
current += 1
return result
}
}
func makeAsyncIterator() -> AsyncIterator {
return AsyncIterator(howHigh: limit)
}
}如您所見,我們定義了一個實現(xiàn) AsyncSequence 協(xié)議的 Counter 結(jié)構(gòu)體。該協(xié)議要求我們返回一個自定義的 AsyncIterator,我們使用內(nèi)部類型解決了這個問題。我們可以決定重寫此示例以消除對內(nèi)部類型的需求:
struct Counter: AsyncSequence, AsyncIteratorProtocol {
typealias Element = Int
let limit: Int
var current = 1
mutating func next() async -> Int? {
guard !Task.isCancelled else {
return nil
}
guard current <= limit else {
return nil
}
let result = current
current += 1
return result
}
func makeAsyncIterator() -> Counter {
self
}
}我們現(xiàn)在可以將 self 作為迭代器返回,并保持所有邏輯的集中。
注意,我們必須通過提供 typealias 來幫助編譯器遵守 AsyncSequence 協(xié)議。
next() 方法負責對整體數(shù)值進行迭代。我們的例子歸結(jié)為提供盡可能多的計數(shù)值,直到我們達到極限。我們通過對 Task.isCancelled 的檢查來實現(xiàn)取消支持。
異步序列的迭代
現(xiàn)在我們知道了什么是 AsyncSequence 以及它是如何實現(xiàn)的,現(xiàn)在是時候開始迭代這些值了。
以上述例子為例,我們可以使用 Counter 開始迭代:
for await count in Counter(limit: 5) {
print(count)
}
print("Counter finished")
// Prints:
// 1
// 2
// 3
// 4
// 5
// Counter finished我們必須使用 await 關(guān)鍵字,因為我們可能會異步接收數(shù)值。一旦不再有預期的值,我們就退出for循環(huán)。異步序列的實現(xiàn)者可以通過在 next() 方法中返回 nil 來表示達到極限。在我們的例子中,一旦計數(shù)器達到配置的極限,或者迭代取消,我們就會達到這個預期:
mutating func next() async -> Int? {
guard !Task.isCancelled else {
return nil
}
guard current <= limit else {
return nil
}
let result = current
current += 1
return result
}許多常規(guī)的序列操作符也可用于異步序列。其結(jié)果是,我們可以以異步的方式執(zhí)行映射和過濾等操作。
例如,我們可以只對偶數(shù)進行過濾:
for await count in Counter(limit: 5).filter({ $0 % 2 == 0 }) {
print(count)
}
print("Counter finished")
// Prints:
// 2
// 4
// Counter finished或者我們可以在迭代之前將計數(shù)映射為一個 String :
let counterStream = Counter(limit: 5)
.map { $0 % 2 == 0 ? "Even" : "Odd" }
for await count in counterStream {
print(count)
}
print("Counter finished")
// Prints:
// Odd
// Even
// Odd
// Even
// Odd
// Counter finished
我們甚至可以使用 AsyncSequence 而不使用for循環(huán),通過使用 contains 等方法。
let contains = await Counter(limit: 5).contains(3)
print(contains) // Prints: true
注意,上述方法是異步的,意味著它有可能無休止地等待一個值的存在,直到底層的 AsyncSequence 完成。
結(jié)論
AsyncSequence 是我們在Swift中熟悉的常規(guī) Sequence 的異步替代品。就像你不會經(jīng)常自己創(chuàng)建一個自定義 Sequence 一樣,你也不太可能創(chuàng)建自定義的異步序列。
參考資料
[1]SE-298: https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md
分享標題:Swift AsyncSequence — 代碼實例詳解
分享URL:http://m.fisionsoft.com.cn/article/cdishec.html


咨詢
建站咨詢
