[Swift] AsyncIteratorProtocol

학습을 위한 번역

원본 링크: https://developer.apple.com/documentation/swift/asynciteratorprotocol

sequence value를 한 번에 하나씩 비동기로 공급하기 위한 type

Declaration

protocol AsyncIteratorProtocol

Overview

AsyncIteratorProtocol은 AsyncSequence protocol의 makeAsyncIterator method가 반환하는 type을 정의한다. 요약하자면, iterator는 비동기 sequence의 value를 생성한다. 그 protocol은 단일 비동기 method를 정의한다.

next() sequence의 다음 element를 생성하거나 sequence의 끝을 알리기 위해 nil을 반환하는 method

당신이 소유한 AsyncSequence를 구현하기 위해, AsyncIteratorProtocol을 준수하는 wrapped type을 구현해라. 다음 예제는 inner iterator를 사용하여 howHigh value에 도달할 때까지 Int value를 단조롭게 생성하는 Counter type을 보여준다. 이 예제가 비동기적이진 않지만, 이건 custom sequence 그리고 iterator의 형태를 보여주고, 이게 만약 비동기 였다면 어떻게 사용해야하는지 보여준다.

struct Counter : AsyncSequence {
    typealias Element = Int
    let howHigh: Int

    struct AsyncIterator : AsyncIteratorProtocol {
        let howHigh: Int
        var current = 1
        mutating func next() async -> Int? {
            // A genuinely asychronous implementation uses the `Task`
            // API to check for cancellation here and return early.
            guard current <= howHigh else {
                return nil
            }

            let result = current
            current += 1
            return result
        }
    }

    func makeAsyncIterator() -> AsyncIterator {
        return AsyncIterator(howHigh: howHigh)
    }
}

호출 부에서는, 다음과 같다:

for await i in Counter(howHigh: 10) {
  print(i, terminator: " ")
}
// Prints: 1 2 3 4 5 6 7 8 9 10

End of Iteration

iterator는 sequence의 끝을 나타내기 위해 nil을 반환한다. next() method로 부터 nil이 반환된 후에(또는 error가 던져진), iterator는 terminal state로 들어가고, next() method에 대한 향후 호출은 모두 nil을 반환한다.

Cancellation

AsyncIteratorProtocol을 준수하는 type은 Swift Task API에서 제공하는 cancellation primitive를 사용해야한다. iterator는 다음을 포함하여 취소를 제어하고 응답하는 방법을 선택할 수 있다.

  • next() 내부에서 현재 task의 isCancelled value를 확인하고 nil을 반환하여 sequence를 종료한다.
  • task에서 checkCancellation()을 호출하면, CancellationError가 발생한다.
  • cancellation에 즉시 반응하기 위해, withTaskCancellationHandler(handler:operation:)호출로 next()를 구현한다.

iterator가 취소 시 삭제해야하는 경우, 위에서 설명한 대로 cancellation을 확인한 후 삭제하거나 reference type인 경우 deinit에서 삭제할 수 있다.