저번 글에서 말했듯이 자바스크립트는 비동기 방식으로 동작합니다.
비동기 코드에서 작업의 순서를 보장하기 위한 방법 중 하나는 콜백이 있습니다.
하지만 순서를 지켜야 할 작업이 여러 개라면 어떨 것 같나요?호출한 콜백은 또다른 콜백을 호출하고 그 콜백은 또 다른 콜백을...이렇게 가독성을 떨어뜨리는 문법을 해결할 또 다른 방법이 있습니다.
이번에는 Promise와 async/await의 비동기 처리에 대해서 알아보겠습니다.
🐸 Promise
Promise라는 객체에는 작업에 대한 상태를 가지고 있습니다.
가지고 있는 상태의 종류는 다음과 같습니다.
- Pending(대기)
- Fulfilled(이행)
- Rejected(거부)
const promise = new Promise((resolve, reject) => {
if (/* 작업 성공 */) {
resolve('작업 성공');
} else {
reject('작업 실패');
}
}
위의 예제처럼 resolve와 reject라는 콜백 함수를 기본으로 제공합니다.
Promise 객체는 생성하는 순간 대기 상태를 가지며,
resolve를 호출하면 이행, reject를 호출하면 거부 상태로 변화합니다.
🐸 Promise chaining
그럼 아까 언급한 콜백 지옥을 Promise는 어떻게 해결할 수 있을까요?
then()은 매개변수로 Promise가 이행했을 때와 거부했을 때를 위한 콜백 함수를 가지고 Promise 객체를 반환합니다.
덕분에 체이닝 문법을 사용하여 순차적으로 작업을 수행할 수 있습니다.
예를 들어, 산타를 위해 주소를 가져와서 포장을 하고 배달하는 코드를 작성한다면 이렇게 할 수 있습니다.
findAddressFromDB(userId)
.then((address) => {
console.log('착한 아이의 주소: ', address);
return pack(address);
}).then((gift) => {
console.log('포장 완료', gift);
return deliver(gift);
}).then(() => {
console.log('배달 완료');
}).catch((error) => {
console.log('오류가 발생했습니다.', error);
});
🐸 async/await
앞에서 나온 체이닝을 사용해도 체인이 길어진다면 가독성이 떨어질 것입니다.
이러한 단점을 async와 await를 통해 보완할 수 있습니다.
예를 들어, 위 체이닝 예제를 async/await 형식으로 다시 작성하면 아래와 같습니다.
async function delivery() {
try {
const address = await findAddressFromDB();
console.log('착한 아이의 주소: ', address);
const gift = await pack(address);
console.log('포장 완료', gift);
const deliver = await deliver(gift);
console.log('배달 완료');
} catch (error) {
console.log('오류가 발생했습니다.', error);
}
}
await는 Promise가 완료될 때까지 기다렸다가 결과를 저장할 수 있습니다.
async로 만들어진 함수 안에서만 await를 사용할 수 있습니다.
async가 앞에 붙여진 함수는 항상 Promise 객체를 반환하는 함수가 됩니다.
이 글을 끝까지 봐주셔서 감사합니다.
틀린 내용이 있다면 댓글로 지적 부탁드립니다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 실행 컨텍스트와 렉시컬 환경 (0) | 2024.10.22 |
---|---|
[JavaScript] 자바스크립트의 일급 함수 (0) | 2024.10.21 |
[Express] 유효성 검사를 해보자 (1) | 2024.09.24 |
[Express] Router 적용하기 (0) | 2024.09.10 |
[Express] 같은 경로의 핸들러 묶기 (0) | 2024.09.09 |