[WWDC21] Meet AsyncSequence
WWDC21 영상보면서 이해한대로 대충 끄적여보기 첼린지
정확한 이해가 필요하신 분들은 영상을 직접 시청하는 것을 권합니다.
아마 내용이 많이 겹치겠지만, 실질적인 사용법 관련해서 더 많이 다룰 것 같은 느낌
0분 37초 - QuakesTool
@main
struct QuakesTool {
static func main() async throws {
let endpointURL = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.csv")!
// skip the header line and iterate each one
// to extract the magnitude, time, latitude and longitude
for try await event in endpointURL.lines.dropFirst() {
let values = event.split(separator: ",")
let time = values[0]
let latitude = values[1]
let longitude = values[2]
let magnitude = values[4]
print("Magnitude \(magnitude) on \(time) at \(latitude) \(longitude)")
}
}
}
asyncSequence라는게 음.. async function을 roop로 돌렸을 때 처리하는 거에 대해서 다뤄지는 거겠죠? sequence라는게 또 Rx에서의 sequence를 보면 또 다른 느낌이라서..
지금 위 코드 예시를 보니 for문에 try await를 써서 async를 처리하는 모습을 보여주고 있네요!
이거 없을 땐 dispatchSemaphore 써서 기다렸는데 확실히 블럭도 줄고 더 간편하네요 👍
3분 24초 - Iterating a Sequence
for quake in quakes {
if quake.magnitude > 3 {
displaySignificantEarthquake(quake)
}
}
아마 비교 분석할려고 예시를 만든 것 같아요! 여기서 딱히 부연설명할 필요는 없는듯..
3분 52초 - How the compiler handles iteration
var iterator = quakes.makeIterator()
while let quake = iterator.next() {
if quake.magnitude > 3 {
displaySignificantEarthquake(quake)
}
}
이건 iterator를 만들어서 수행하는 건데, 다른 느낌이긴한데 이걸 비동기라고 생각해본 적 없는데… complier가 handling하는 게 어떤 차이가 있는지 모르겠네요..
4분 11초 - How the compiler handles asynchronous iteration
var iterator = quakes.makeAsyncIterator()
while let quake = await iterator.next() {
if quake.magnitude > 3 {
displaySignificantEarthquake(quake)
}
}
현재 새로나온 비동기 제어를 위해 await 키워드를 추가한 예시입니다. 음…
아마도 차이라고 치면 await가 await하는 작업을 suspend하는 거니까 complete call할 때까지 다른 작업하다가 complete call되면 다시 진행되는 것 같다.. 음.. 그러면 그냥 써도 되는걸 await를 붙여서 loop 자체도 async하게 돌릴 수 있다 뭐 그런건가..
4분 28초 - Iterating an AsyncSequence
for await quake in quakes {
if quake.magnitude > 3 {
displaySignificantEarthquake(quake)
}
}
이것도 뭐 위에랑 느낌만 다르지 똑같은 예시라고 생각이 듭니다.
7분 15초 - Concurrently iterating inside an async task
let iteration1 = async {
for await quake in quakes {
...
}
}
let iteration2 = async {
do {
for try await quake in quakeDownload {
...
}
} catch {
...
}
}
//... later on
iteration1.cancel()
iteration2.cancel()
이런 식으로 Task 단위로 만들어서 처리도 가능합니다… 어… 근데 좀 참신한거 없니.. 이거 다 봤던 내용인데..
7분 56초 - Reading bytes from a FileHandle
for try await line in FileHandle.standardInput.bytes.lines {
...
}
8분 16초 - Reading lines from a URL
let url = URL(fileURLWithPath: "/tmp/somefile.txt")
for try await line in url.lines {
...
}
8분 49초 - Reading bytes from a URLSession
let (bytes, response) = try await URLSession.shared.bytes(from: url)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 /* OK */
else {
throw MyNetworkingError.invalidServerResponse
}
for try await byte in bytes {
...
}
9분 12초 - Notifications
let center = NotificationCenter.default
let notification = await center.notifications(named: .NSPersistentStoreRemoteChange).first {
$0.userInfo[NSStoreUUIDKey] == storeUUID
}
11분 10초 - Using an AsyncStream
let quakes = AsyncStream(Quake.self) { continuation in
let monitor = QuakeMonitor()
monitor.quakeHandler = { quake in
continuation.yield(quake)
}
continuation.onTermination = { _ in
monitor.stopMonitoring()
}
monitor.startMonitoring()
}
아.. 이건 예시 코드가 없어서 직접 썼다.. handler로 제어하는 코드에서 yield가 정확히 뭘 의미하는지 모르겠는데 아마도 값을 넘겨주는 거겠죠? 아무튼.. continuation을 통해서넘겨진게 결국 quakes로 다 담겨서 넘어오는거같습니다. onTermination은 아마… Task가 cancel될 때 호출되지 않을까요..
이것도 감이 아직 안오는데 써봐야 알듯..
Hello AsyncStream
- AsyncSequence created with callbacks or delegates
- Handles buffering
- handles cancellation