1️⃣ 核心概念
AsyncSequence 是一个异步序列接口,允许你按顺序异步获取元素,每次获取可能需要挂起等待数据。
- 类似于
Sequence,但元素是 异步生成的 - 迭代器遵循
AsyncIteratorProtocol:
protocol AsyncIteratorProtocol {
associatedtype Element
mutating func next() async throws -> Element?
}
-
next()是异步函数:- 返回一个元素或
nil(序列结束) - 可以挂起等待异步数据
- 返回一个元素或
2️⃣ 使用示例
struct Counter: AsyncSequence {
typealias Element = Int
let max: Int
struct AsyncIterator: AsyncIteratorProtocol {
var current = 0
let max: Int
mutating func next() async -> Int? {
guard current < max else { return nil }
let value = current
current += 1
try? await Task.sleep(nanoseconds: 500_000_000) // 模拟异步等待
return value
}
}
func makeAsyncIterator() -> AsyncIterator {
AsyncIterator(current: 0, max: max)
}
}
for await n in Counter(max: 3) {
print(n) // 输出 0 1 2,每次等待 0.5 秒
}
for await会自动调用next(),并挂起当前 Task,等待异步结果- 使用
await是因为元素可能尚未准备好
3️⃣ 底层原理
① AsyncSequence → AsyncIteratorProtocol
AsyncSequence仅提供makeAsyncIterator()- 核心异步逻辑在
next()中实现
② next() 返回异步结果
-
next()是async函数 → 可以挂起 -
底层由 continuation 或 Swift Concurrency runtime 支持:
- 当前 Task 被挂起
- 等待异步事件(网络、定时器、生产者)完成
- 生成新元素后 resume 任务
③ 内部使用 Continuation / Task
-
Swift runtime 会为挂起的
next()创建 continuation(类似回调容器) -
当数据可用:
- 调用
resume,恢复被挂起的 Task - Task 恢复执行
for await的下一次循环
- 调用
for await item in AsyncSequence {
↓
next() async called → Task suspended → runtime保存continuation
Data ready → continuation.resume() → Task恢复
④ 异步流模型
-
可以想象 AsyncSequence 是一个 异步数据流:
- 生产者:生成数据(可以是后台线程、定时器、网络回调)
- 消费者:
for await循环读取数据 - Task + continuation → 协作式挂起恢复
4️⃣ AsyncStream / AsyncThrowingStream
Swift 提供了方便的 构建 AsyncSequence 的工具:
let stream = AsyncStream<Int> { continuation in
Task {
for i in 0..<3 {
continuation.yield(i)
try? await Task.sleep(nanoseconds: 500_000_000)
}
continuation.finish()
}
}
for await n in stream {
print(n)
}
yield→ 放入 stream 队列,挂起的 Task 会被 resumefinish()→ 结束 sequence,next()返回 nil- 内部依赖 continuation + Task 排队 机制
5️⃣ 总结底层原理
- AsyncSequence/AsyncIteratorProtocol 定义异步迭代接口
- next() async 挂起 Task,等待数据生成
- Swift runtime + continuation 保存 Task 状态
- 数据生成 / yield / finish → resume Task
- for await 自动调用 next() 并挂起/恢复,像同步 for 循环一样可读
6️⃣ 面试必背结论
Swift 的 AsyncSequence 通过 async Iterator 协议和
next()async 方法实现异步迭代。底层使用 Task + continuation 模型:当元素尚不可用时 Task 挂起,生产者生成数据后通过 continuation 恢复 Task,从而实现协作式异步流的安全迭代。