WWDC Notes: Meet AsyncSequence
Published on: June 9, 2021Map, filter, reduce, dropFirst all work in async sequences:
for try await someThing in async.dropFirst() {
}
For example.
AsyncSequence suspends on each element and receives values asynchronously from the iterator. AsyncSequences either complete with success or stop when an error is thrown.
Implementing an AsyncSequence follows all the rules that a normal sequence follows. Its next()
returns nil
when it’s completed for example.
An async iterator also consumes its underlying collection.
Things like break
and continue
work in async sequences too.
You can cancel an iteration by holding on to its Task.Handle
when you wrap it in async
:
let handle = async {
for await thing in list {
// ...
}
}
handle.cancel()
Reading files from a URL is commonly done async. You can use URL.lines
for this. It works for network and local resources.
URLSession
has a bytes(_:)
function to enable roughly the same but with more control.
NotificationCenter notifications can be awaited too. You can even await one notification:
// listens for 1 notification only
let center = NotificationCenter.default
let notification = await center.notifications(named: .SomeNotification).first { notification in
print(notification)
}
Callbacks that are called multiple times, and some delegates are good candidates for async sequences.
Start / stop / handle pattern is a good candidate. Sounds similar to location managers.
let stream = AsyncStream(Output.self) { continuation in
let object = SomeObject()
object.handler = { element in
continuation.yield(element)
}
object.onTermination = { _ in
object.stop()
}
// starts producing values
object.start()
}
AsyncStream
is the easiest way to create your own asynchronous sequences. They also handle buffering (not sure what that means in this case).
There’s also a throwing version: AsyncThrowingStream
.
Note:
AsyncStream
does not appear to be present in Beta 1