자바스크립트에서 비동기 함수를 순차적으로 호출하는 방법 중에는 콜백, Promise, async 함수를 이용한 방법이 있습니다.
콜백을 이용하는 방법
콜백으로 비동기 로직을 처리하기 위해서는 비동기 로직 후에 그 다음 함수가 실행되도록 전의 비동기 함수에 callback 파라미터를 받아 함수 안에서 비동기 로직이 모두 실행된 다음 callback으로 다음 함수를 실행할 수 있도록 해야합니다.
다음과 같은 문제가 있었습니다.
비동기 함수 다음 처리해야 하는 로직이 있을 때마다 콜백을 argument로 넘겨줘야 한다.
에러 처리를 할 경우 에러 핸들링 함수도 콜백으로 넘겨주어야 한다.
순서대로 진행되어야 하는 함수가 많을수록 더 깊은 콜백이 필요하다.
Promise를 쓰는 이유
Promise의 resolve를 통해 다음 순서에 필요한 콜백을 parameter로 넘겨줄 필요 없이 호출된 코드 라인으로 값을 넘겨줄 수 있다.
resolve를 통해 전달된 결과 값을 then으로 받아 처리할 수 있다.
reject를 통해 에러를 전달받아 핸들링 할 수 있다.
Promise를 이용하는 방법
콜백 지옥과 Promise.then 중첩의 차이점
콜백과 달리 promise로 순서가 있는 비동기 함수를 실행할 때 promise의 리턴값이 then으로 넘겨지기 때문에 then이 계속해서 중첩되게 된다.
async await 키워드를 이용하는 방법
위의 두 코드는 같습니다. 두 번째 코드는 첫 번째 코드의 syntatic sugar라고 할 수 있습니다.
await
await연산자는 Promise를 기다리기 위해 사용됩니다. 연산자는 async function 내부에서만 사용할 수 있습니다.
await vs return vs return await
다음 예제를 통해 async await이 어떻게 동작하게 되는지 예측해보며 개념에 대한 이해를 더 정확하게 체크할 수 있었습니다. 해당 예제는 여기에서 가져왔습니다.
just calling
waitAndMaybeReject는 async 함수이기 때문에 무조건 Promise를 반환합니다.
일반 함수였다면 50퍼센트의 확률로 'yay'라는 문자열을 반환했겠지만,
async 함수이기 때문에 50퍼센트의 확률로 'yay'를 resolve하는 Promise 혹은 Error('Boo!')로 reject하는 Promise 가 반환됩니다.
두 값 모두 resolve, reject가 되지 않은 pending 상태의 Promise이기 때문에 위의 코드에서 절대 에러가 발생하지 않게 됩니다.
awaiting
await 키워드를 사용하므로써, pending상태의 Promise가 resolve 또는 reject 처리가 됩니다.
waitAndMaybeReject에서 isHeads가 true이면 foo에서 resolve처리가 되고, isHeads가 false이면 foo에서 error가 발생하게 됩니다.
returning
await 키워드 없이 waitAndMaybeReject를 바로 return할 경우에도 첫번째 just calling의 경우와 같이 pending 상태의 Promise이기 때문에 catch 블록이 절대 실행되지 않습니다.
return-awaiting
그렇다면 Promise를 받아 await 처리를 하고, 이를 return하는 async 함수는 어떻게 동작할까요?
isHeads = true로 나왔다면
waitAndMaybeReject로부터 pending 상태의 Promise를 받는다.
await를 통해 resolve 처리한다.
resolve 된 경우 이 값을 다시 Promise.relove('yay')로 반환한다.
isHeads = false로 나왔다면
waitAndMaybeReject로부터 pending 상태의 Promise를 받는다.
await를 통해 reject 처리한다.
Error('Boo!')로 인해 catch 블록이 실행된다.
try-catch 문이 없다면 Promise의 resolve, reject 처리가 된 결과값을 다시 Promise로 반환하는 것은 redundant한 일입니다.
그렇기 때문에 try-catch 블록을 사용하지 않는 경우에 한에 이를 제한하는 eslint 규칙이 존재합니다.