Swift async-await 대 클로저
Dec 07 2022
Swift await는 호출된 asyncmethod가 반환될 때까지 컨텍스트를 캡처하고 실행을 일시 중단하여 작동합니다. 주변 컨텍스트를 캡처하여 유사하게 작동하는 또 다른 기능은 이스케이프 클로저입니다.
Swift 는 컨텍스트를 캡처하고 호출된 메서드가 반환 await될 때까지 실행을 일시 중단하여 작동 합니다. async주변 컨텍스트를 캡처하여 유사하게 작동하는 또 다른 기능은 이스케이프 클로저입니다. 따라서 async-await호출은 이스케이프 클로저와 동일하다고 상상할 수 있습니다. 메서드가 있는 메서드를 볼 때마다 async정신적으로 해당 메서드를 이스케이프 완료 처리기로 대체합니다.
func run() async
func run(_ completion: @escaping () -> Void)
동등한 코드가 있는 간단한 시나리오
class Foo {
func before() { /*...*/ }
func after() { /*...*/ }
func doStuff() async { /*...*/ }
func doStuff(_ completion: @escaping () -> Void) { /*...*/ }
}
extension Foo {
func run() async {
before()
await doStuff()
after()
}
}
extension Foo {
func run(_ completion: @escaping () -> Void) {
before()
doStuff {
self.after()
completion()
}
}
}
func doStuff() async -> Int
let ret = await doStuff()
print("\(ret)")
func doStuff(_ completion: @escaping (Int) -> Void)
doStuff { ret in
print("\(ret)")
}
func div(_ a: Int, _ b: Int) async throws -> Double {
if b == 0 {
throw FooError.divideByZero
}
return Double(a) / Double(b)
}
do {
let ret = try await div(1, 0)
print("\(ret)")
} catch {
print("\(error)")
}
func div(_ a: Int, _ b: Int, _ completion: @escaping (Double) -> Void) throws {
if b == 0 {
throw FooError.divideByZero
}
completion(Double(a) / Double(b))
}
do {
try div(1, 0) { ret in
print("\(ret)")
}
} catch {
print("\(error)")
}
async호출이 수신자에게 자연스럽게 전파되는 방식에 주목하십시오 . doStuff() async따라서 make에 대한 호출 run() async도 마찬가지입니다. 이는 대부분의 경우 완료 핸들러에 대해서도 의미가 있습니다. 그리고 비동기 동작을 전파하지 않으려면, 즉 async메서드를 메서드로 변환하려면 완료 핸들러를 받는 synca를 사용해야 하며 Task내부에서 래핑하는 것과 동일합니다.DispatchQueue.async { ... }
func run() {
before()
Task {
await doStuff()
after()
}
}
func run() {
before()
DispatchQueue.global().async {
self.doStuff {
self.after()
}
}
}
비동기 메서드를 차례로 호출하려는 경우 정신 모델은 동일하게 유지됩니다.
func doStuff() async {}
func doMoreStuff() async {}
before()
await doStuff()
await doMoreStuff()
after()
func doStuff(_ completion: @escaping () -> Void) {}
func doMoreStuff(_ completion: @escaping () -> Void) {}
before()
doStuff {
self.doMoreStuff {
self.after()
}
}
func run() async {
before()
async let task1: Void = doStuff()
async let task2: Void = doMoreStuff()
_ = await [task1, task2]
after()
}
func run(_ completion: @escaping () -> Void) {
before()
let group = DispatchGroup()
group.enter()
doStuff { group.leave() }
group.enter()
doMoreStuff { group.leave() }
group.notify(queue: DispatchQueue.global()) {
self.after()
completion()
}
}
async-await에 대한 더 나은 멘탈 모델을 갖는 것은 그것이 우리를 어떤 종류의 함정으로부터 구하는지, 그리고 완료 핸들러에서 async await로 마이그레이션하는 방법을 이해하는 데 도움이 됩니다.

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































