
지난 번, 비동기와
Promise에 대해 얘기했던 내용은 여기.
오늘은 더 나아가async와await에 대해 알아보려 한다!
: 지난 번 글에서 then() 을 카페에서 음료를 주문하고 받는 진동벨에 비유했다.
이번엔 당신이 친구들과 카페에 갔다고 가정해보자. 나중에 서로 돈 보내면서 더치페이하기 귀찮으니 각자 결제해서 음료를 받기로 했다.
친구는 총 6명이고, 여러 번 결제를 하며 진동벨을 인원 수에 맞게 6개 지급받았다.
진동벨이 1개 울릴 때마다 각자 불려나가듯 음료를 받아온다. 그렇게 총 6번 왔다갔다를 해서 모두가 음료를 받아올 수 있었다.
이런 경우가 Promise의 한계라고 볼 수 있다. then()이 6번, 혹은 그 이상 이어지게 된다면? .. 😫
fetchData()
.then((response) => {
return processResponse(response);
})
.then((processedData) => {
return saveData(processedData);
})
.then(() => {
console.log("All tasks completed!");
})
.catch((error) => {
console.error(error);
});
이처럼 then() 과 catch()의 체인이 길어질수록 코드가 복잡해지고 가독성이 떨어지는 한계점이 있다. 여러 단계의 비동기 작업을 연결해야 하는 경우 코드가 중첩되면서 "콜백 지옥"과 유사한 모습이 될 수 있는 거다.
안그래도 계약서와 계약 이행 부분이 분리돼있어 읽기 힘들어 죽겠는데 체인이 길어지기까지 한다면.. 그게 내가 짠 코드도 아니라서 해석하는 데 시간이 꽤 걸리는 코드라면.... 💢
하지만 이런 경우에는 편해진다. 친구들이 각자 6번 결제를 해서 각기 다른 음료를 받기로 했지만 센스있는 직원이 진동벨 1개에 모두 할당해주어 "음료가 모두 완성되면 불러드릴게요~" 라고 유도리있게 해주는 거다 !
그럼 친구 6명이 모두 움직일 필요가 없어지고, 각각 음료가 완성되면 차곡차곡 쌓아 한 번에 전달해주니 서로 무슨 음료까지 완성됐는지 피차 확인할 필요도 없고 흐름이 깔끔해진다.
이래서 async/await이 필요한거다. 왜 개발자들이 Promise가 싫다고 칭얼댔는지 이제 이해가 가기 시작함.. ^,^
: 우리도 배달 음식을 주문해놓고 중간 중간 "배달 중", 혹은 "배달 완료" 상태 변화를 확인해가며 음식을 받는 것보다 배달이 오면 노크하고 문 앞에 두고 가는 방식을 선호하듯,
개발자들도 데이터 파싱이 완료된 시점에 자연스럽게 처리하는 방식을 선호한다.
async function fetchDataAndProcess() {
try {
const response = await fetchData();
const processedData = await processResponse(response);
await saveData(processedData);
console.log("All tasks completed!");
} catch (error) {
console.error(error);
}
}
async / await을 사용하면 코드가 위에서 아래로 (기존 자바스크립트의 동작 방식대로) ! 동기적으로 읽히는 구조로 바뀐다. (Promise처럼 선언과 실행 구문을 왔다갔다 할 필요가 없다!)Promise가 계약서 작성과 이행이 분리되어 있어 작업 흐름을 따로따로 봐줘야 하지만, async / await 은 작성과 이행을 한 곳에서 처리하기 때문에 읽고 이해하기가 훨씬 쉬워진 것이다 ❗❗이번엔 에러 처리에 관해서 생각해보자.
Promise로 작성된 구문은 이러하다.
function getContract() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("계약 완료!"), 1000);
});
}
getContract()
.then((contract) => {
console.log(contract); // "계약 완료!"
return "이행 시작!";
})
.then((action) => console.log(action)) // "이행 시작!"
.catch((error) => console.error(error)); // 에러 처리
Promise는 then() 체인을 통해 단계별로 작업을 연결해야 한다. 따라서 에러가 발생하면 각 단계마다 에러를 신경써주거나, 마지막 catch()에서 처리해야 한다.💢 중간 단계에서 발생한 에러를 포착하려면 각 단계마다 추가 로직이 필요할 수 있다는 것이다.async/await으로 작성된 구문은 어떨까?
async function handleContract() {
try {
const contract = await new Promise((resolve) =>
setTimeout(() => resolve("계약 완료!"), 1000)
);
console.log(contract); // "계약 완료!"
const action = "이행 시작!";
console.log(action); // "이행 시작!"
} catch (error) {
console.error(error); // 에러 처리
}
}
handleContract();
try/catch 블록을 사용해 에러를 한 번에 관리할 수 있다❗❗ 에러를 한 번에 처리할 수 있다는 것만큼 개발자에게 달콤한 것은 없지 .. 🍭아래 코드를
async/await구문으로 바꾸면?function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => { resolve("데이터가 준비되었습니다!"); }, 2000); }); } fetchData().then((data) => { console.log(data); });
async function fetchData() {
const data = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve("데이터가 준비되었습니다");
}, 2000);
});
console.log(data);
}
fetchData();
아직 이 둘을 왔다갔다 변환하는 건 어려울 수 있어도, 두 가지의 개념과 차이라도 이해했다면 어느정도 비동기를 정복했다고 볼 수 있다😎
여러분은 얼만큼 이해하셨나요 !!!!
잘봤습니다아아아아👍👍👍