Swift concurrency
AsyncSequence
A type that provides async, sequential, iterated access to its elements.
Overview
for await rollNumber in RollNumberGenerator(totalStudents: 1000) {
// TODO: -
}
Implementation
When you define custom AsyncSequence, you will conform to 2 protocols, AsyncSequence and AsyncIteratorProtocol those will required you to defined associated type called Element, the AsyncSequence defines a makeAsyncIterator() method. This returns an instance of type AsyncIterator which defines its method next() as async, which requires caller to wait for next value with the await keyword.
领英推荐
struct RollNumberGenerator: AsyncSequence, AsyncIteratorProtocol {
typealias Element = Int
let totalStudents: Int
var currentStudent = 1
mutating func next() async -> Int? {
guard !Task.isCancelled else {
return nil
}
guard currentStudent <= totalStudents else {
return nil
}
let result = currentStudent
currentStudent += 1
return result
}
func makeAsyncIterator() -> RollNumberGenerator {
self
}
}
AsyncSequence Methods
Single-value methods doesn’t need await-in loop, you can make single await call for example you wanna check some specific roll number
let someSpecialNumber = await RollNumberGenerator(totalStudents: 500)
.first(where: { $0 == someRollNumber })
Methods that return another AsyncSequence for example the map(_:) method returns a AsyncMapSequence, these returned sequences don’t eagerly await the next member of the sequence, which allows the caller to decide when to start work.
In code example map(_:) method transforms each Int received from RollNumberGenerator sequence into a string and you can see doesn't require await-in loop because it returns another async sequence, but when we will iterate over mapped sequence we will need await-in loop as we used Async sequence in the beginning.
let categories = RollNumberGenerator(totalStudents: 50)
.map {
// Any special operation / check
$0 + 1 % 2 == 0 ? "Section A" : "Section B"
}
for await category in categories {
// TODO: -
}