[Async/Await] Structured Concurrency

async-let

  • As Is
let (data1, response) = try await URLSession.shared.data(from:)

let (data2, responese) = try await URLSession.shared.data(from:)
  • To Be
async let (data1, response) = URLSession.shared.data(from:)

async let (data2, response) = URLSession.shared.data(from:)

let score = try? JSONDecoder().decode(CreditScore.self, from try await data1)

let score = try? JSONDecoder().decode(CreditScore.self, from try await data2)

As Is는 데이터가 나올 때 까지 해당 코드에서 suspend 되지만 To Be 코드처럼 사용하면 decode 하는 부분에서 suspend. (URLSession 코드 두 개는 Concurrency 하게 동작함. data1의 결과를 기다리지 않고 data2를 받을 수 있음.)

async-let loop

func someAsyncFunc(id: Int) async throws -> Double {  }

let ids = [1, 2, 3, 4, 5]

Task {
   for id in ids {
      let result = try await someAsyncFunc(id: id)
   }
}

id가 여러 개 인 경우 for loop을 사용해 async 메서드를 수행할 수 있다. 이 경우 하나의 id에 대한 async func 작업이 완료될 때 까지 다음 id에 대한 작업은 suspend 된다.

cancelling task

Task {
   for id in ids {
      do {
         try Task.checkCancellation()
         let result = try await someAsyncFunc(id: id)
      } catch {
         print(error)
      }
   }
}

Task.checkCancellation() : task가 cancel되는 경우 error를 throw

Group Tasks

withThrowingTaskGroup(of:returning:body:)

실행하고 싶은 task를 TaskGroup에 넣음. group에서 작업한 결과 값의 타입은 of에 표기한다.

withTaskGroup에서 외부의 변수(self.xx)에 접근할 때는 groupTask에서 값이 return된 이후 반복문에서 group을 사용하는 부분에서 접근 가능하다.

WWDC

Leave a comment