await
을 적용할 때 어떤 일이 일어나는지 살펴봅시다. 비록 async 함수가 동기식 함수와 유사하게 보이지만, 그 이면은 callbacks으로 가득 채워진 자바스크립트 코드처럼 비동기적 입니다. 이미 짐작하겠지만, await
은 자바스크립트로 하여금 내부적으로 then()
함수를 호출하도록 합니다.await
키워드는 자바스크립트로 하여금 이벤트 루프의 다음 차례까지 실행을 일시 정지 시키도록 합니다. 아래 코드에서 await 이후, console.log()
는 ++currentId
코드 뒤에 실행됩니다.then()
이 완전 동기식이라도 다음 차례에 작동된다는 점을 유의하세요. 이것은 await
는 최소한 다음 차례까지는 실행을 일시 정지 시킨다는 것을 뜻합니다. 만약 onRejected(err)
를 호출한다면 await
키워드는 여러분 함수 본체로 err
를 throws합니다.return
은 그 함수가 반환하는 promise를 "해결" 한다는 것을 기억하세요. 이것은 여러분이 promise도를 return
할 수 있다는 것을 뜻합니다. await
와 return
의 차이점은 무었을까요? 답은 이렇습니다. promise에 await
할 경우, 자바스크립트는 그 async 함수의 실행을 일 시정지시킨 후에 재개시키지만, promise를 return
한다면 그 async 함수의 수행을 종료해 버리고 return된 함수를 재개하지 않습니다.await
가 어떻게 작동하는지 알아내기에는 의미가 좀 함축적입니다. 여러분이 await p
를 try/catch
로 감싸고 p
를 "거절" 처리하면 error를 catch할 수 있습니다. 그대신 return p
한다면 어떨까요?try/catch
는 여러분이 return한 "거절"한 promise를 catch 하지 못한다는 점에 주목하기 바랍니다. promise가 "거절"일 때, 왜 await
만이 error를 catch 할까요? 그것은 await는
실행을 재개할 때 error를 throw 하기 때문입니다. promise를 return
하면 자바스크립트는 여러분의 async 함수 본체의 실행을 멈추고 이 async 함수의 promise에 대해 resolve()
를 수행해 버립니다.await
을 하면, 자바스크립트는 그 async 함수의 실행을 일시 정지 시키고 그 promise가 "정착"되면 다시 재개합니다. await
이후, 자바스크립트가 여러분의 async 함수를 재개할 때, 만약 await 한 promise가 "거절" 상태면 그 그 거절값인 error를 던지는 것입니다. 아래는 promise에 await 할 경우 어떤 일이 발생하는지 보여주고 있습니다.return
할 때, 여러분의 그 promise는 자바스크립트 실행 환경으로 가버리고 다시 코드로 돌아오지 못합니다. 그래서 example 3.4에서 try/catch
가 error를 다루지 못한 것입니다. 아래 예들은 error를 catch
하는 몇 가지 대안들입니다. example 3.5는 await p
결과를 v
변수에 할당하고 그 변수를 반환합니다. 그리고 example 3.6은 return await
를 이용합니다.return await
은 자바스크립트 비전문가에게는 다소 어렵게 느껴집니다. 그래서 일반 개발자가 비동기 코드를 쉽게 사용할 수 있도록 하자는 목적에서 살짝 벋어납니다.await p
가 자바스크립트로 하여금 여러분의 async 함수를 일시 정지 시키고 p.then()
를 호출한다는 것을 알았습니다. 그리고 promise가 "정착"될 때 수행을 재개한다는 것도을 알았습니다. 그렇다면 여러 async 함수들이 병렬로 수행될 때는 이것은 어떤 의미를 가질까요?setImmediate()
같은 구조는 분리된 스레드에서 로직을 수행하고 무한 루프가 수행되는 동안에도 출력을 하지만 자바스크립트는 이것을 허용하지 않습니다.foo(), bar()
그리고 baz()
함수들은 모두 분리되어 동작합니다.O(n^5)
클러스터링 알고리즘을 수행했습니다.await
으로 일시 정지 시키거나 return
또는 throw
를 통해 함수를 종료하지 않는다면 async 함수는 어떤 간섭 없이 처리될 것이라는 점입니다. 상식적으로 자바스크립트는 여전히 단일 쓰레드에서 수행되기 때문에 두 개의 비동기 함수는 동시에 동작할 수 없습니다. 하지만 await
를 통해 여러분의 async 함수를 일시 정지 시킴으로써, 이벤트 루프로 진입하게 하여 다른 함수들이 수행될 기회를 가질 수 있도록 할 수 있습니다.generators
와 공통점이 많습니다. generators는 2015년도판 자바스크립트 규격의 특징입니다. 비동기 함수와 같이, generator 함수도 일시 정지되고 후에 재개될 수 있습니다. 다만, async 함수와 generators 함수 사이에는 두 가지 중요한 차이점이 있습니다.await
이 아닌 yield
키워드를 사용합니다. next()
를 호출하여 generator 함수를 재개합니다. yield
, next()
를 사용하여 generator 함수를 일시 정지 시키거나 재개하는 사례입니다.co
'입니다. 다음은 async/await 대신에 'co'를 사용하는 사례입니다.yield
할 지 다룰 수 있습니다.yield 1
을 오류로 다룬다는 것은 수많은 오류들을 catch하는데 도움을 줍니다. 하지만 많은 불필요한 오류를 야기하기도 합니다. async/await에서, await 1
은 정상이고 값 1로 평가하며 이것이 좀 더 견고해 보입니다.generator.next()
와 onFulfilled
출력합니다.generator.next(), onFulfilled
등은 출력하지 않습니다. Async/await의 onFulfilled은 사용자 모드가 아닌 자바스크립트 인터프리터 모드에서 동작하기 때문입니다.await
하지 마세요.await 1
이 가능하다고 그렇게 해야만 하는 것은 아닙니다. 많은 async/await의 초보자들은 await을 오용하거나 남용하곤 합니다.await
을 사용하세요. 결코 promise가 될 수 없거나, promise 일 수도 있다고 거짓으로 암시하는 값에는 await
을 할 이유는 없습니다.findSubstr()
함수를 async로 만드는 유일한 이유는 실행을 일시 정지 시켜서 다른 함수들로 하여금 example 3.10 처럼 수행하도록 할 때입니다. 이것은 findSubstr()
가 대량의 배열을 처리한다고 할 때나 유용한 것입니다. 이 경우, 다른 작업들이 처리될 기회를 갖도록 하기 위해 await new Promise(setImmediate)
를 사용해야 합니다.return
을 사용하세요.forEach(), map()
같은 배열 도우미 함수에는 await
사용보다 loop 를 사용하세요.await
을 해도 test()
는 일시 정지하지 않습니다..catch()
로 처리하세요.asyncFn().catch()
는 asyncFn()
함수 내부에서 발생하는 모든 오류 들(동기 또는 비동기 오류)을 처리합니다. example 3.4: try/catch
는 p
가 실패면 return p
로 발생하는 오류 들을 처리하지 못했던 것을 기억하기 바랍니다..catch()
에서 잡을 수 있습니다. .catch()
가 없는 async/await 코드를 보게 된다면 어딘가 처리되지 못할 오류가 존재하게 되다는 것을 명심하세요. 좋은 async/await 코드는 모든 async 함수 호출이 .catch()
로 잡힐 수 있도록 하는 wrap()
함수 같이 집중화된 기법을 사용합니다.then()
함수입니다. await 는 내부적으로 then()
을 호출하고 onFulfilled()
또는 onRejected()
가 호출될 때까지 현재 async 함수를 일시 정지 시킵니다. 이것은 여러분이 어떤 객체라도 then()
함수를 추가함으로써 그 객체가 async/await와 상호 작동 하도록 만들 수 있다는 것을 의미합니다.exec()
함수를 경유하는 콜백들 만 지원합니다. then()
함수를 구현함으로써 이 HTTPRequests 클래스가 async/await와 작동하도록 해보세요.forEachAsync()
함수를 구현하세요. fn()
을 호출합니다. forEachAsync()
는 다음 요소를 이어가기 전에 현재 요소의 fn()
을 기다려야 합니다.