[JavaScript] async await로 비동기 처리 개선하기
이전 게시글 Promise로 callback 지옥 무찌르자에서 확인한 promise로 비동기 처리하는 방법을 조금 더 깔끔하게 처리할 수 있도록 async await을 배워보겠습니다.
async await
◆ 가독성
async await는 비동기 처리를 보다 더 깔끔하게 처리할 수 있는 방법입니다. 사용은 아래와 같이할 수 있습니다.
async function asyncFn() {
await 비동기함수();
}
위와 같이 async, await 만 추가하면 사용할 수 있습니다. 그럼 이게 왜 promise만 사용하는 것보다 더 좋을까요? 우선 가독성이 promise 보다 더 좋습니다. 아래 예시를 참고해봅시다.
function getData_1() {
return new Promise(resolve => {
resolve("data1");
});
}
function getData_2() {
return new Promise(resolve => {
resolve("data2");
});
}
getData_1().then(console.log).then(getData_2).then(console.log);
promise를 사용하여 비동기 처리를 하게 되면 위와 같이 작성해야합니다. 그럼 .then.then.then으로 chaining을 하여야 하는데 개수가 늘어나면 가독성이 좋지 않습니다. async await은 문제를 쉽게 해결할 수 있습니다.
function getData_1() {
return new Promise(resolve => {
resolve("data1");
});
}
function getData_2() {
return new Promise(resolve => {
resolve("data2");
});
}
(async () => {
const data_1 = await getData_1();
const data_2 = await getData_2();
console.log("data_1", data_1);
console.log("data_2", data_2);
})();
간단하게 함수를 사용하기 위해 즉시 실행 함수를 사용하였습니다. 우선 chaining이 없어져 더 코드가 깔끔해보이죠? 가독성이 더 좋아집니다.
◆ 서로 연관 있는 비동기, 연관 없는 비동기
추가로 비동기 처리할 때 사용하면 좋은 함수 몇 가지를 소개해드리겠습니다. 비동기 함수를 여러 개 처리할 때 중요한 것 중 하나는 각각의 비동기 처리에 대해 서로 연관이 있는 지 없는 지 입니다. 우선 서로 연관이 있는 비동기 처리 먼저 확인해보겠습니다. 아래 비동기 코드는 getData_2를 실행하기 위해서는 앞서 꼭 getData_1이 실행되어야 합니다.
function getData_1() {
return new Promise(resolve => {
setTimeout(() => resolve("data1"), 3000);
});
}
function getData_2() {
return new Promise(async resolve => {
setTimeout(() => resolve("data2"), 3000);
});
}
async function getDatas() {
const data1 = await getData_1();
const data2 = await getData_2();
return [data1, data2];
}
getDatas().then(console.log);
위 코드를 실행하면 총 6초가 소요됩니다. getData_1 함수에서 3초, getData_2 함수에서 3초가 소요되기 때문입니다. 이 경우는 어쩔 수 없습니다. 순서가 정해져있기 때문이죠. 꼭 getData_2를 실행하기 위해서는 사전 작업인 getData_1이 시작되어야 하기 때문입니다. 그러나 만약 2개의 비동기 함수가 서로 순서에 영향을 미치지 않으면 어떻게 될까요? 굳이 getData_1이 실행되고 나서 getData_2를 실행시키는 것이 아니라 동시에 실행시켜도 되겠죠? 이러한 것을 할 수 있도록 하는 함수가 Promise.all 함수 입니다. 아래 코드를 확인해봅시다.
function getData_1() {
return new Promise(resolve => {
setTimeout(() => resolve("data1"), 3000);
});
}
function getData_2() {
return new Promise(async resolve => {
setTimeout(() => resolve("data2"), 3000);
});
}
function getDatas() {
return Promise.all([getData_1(), getData_2()]);
}
getDatas().then(console.log);
위 함수를 실행하면 3초가 소요됩니다. getData_1, getData_2를 동시에 호출하기 때문입니다. 이렇게 서로 연관이 없는 비동기 처리는 동시에 요청할 수 있습니다. 그런데 이러한 경우도 있을 수 있습니다. 선착순 즉, 더 빨리 응답이 온 비동기 처리가 필요하다. 어떤 비동기 처리인지는 모르겠고 더 빨리 응답이 온 것이 필요하다. 이러한 경우는 Promise.race 함수를 사용하시면 됩니다. 아래 코드를 확인해봅시다.
function getData_1() {
return new Promise(resolve => {
setTimeout(() => resolve("data1"), 1000);
});
}
function getData_2() {
return new Promise(resolve => {
setTimeout(() => resolve("data2"), 3000);
});
}
function getData() {
return Promise.race([getData_1(), getData_2()]);
}
getData().then(console.log);
이러한 경우는 getData_1이 1초로 더 빠르게 응답이 오기 때문에 data1만 출력이 된 것을 확인할 수 있습니다 (직접 코드를 실행해보세요).
여기까지 callback, callback 지옥, promise, async await를 알아보았습니다. 도움이 약간이라도 되면 좋겠습니다.
참고자료
마지막
해당 내용은 틀릴 수도 있습니다. 틀린 내용이 있으면 조언 부탁드립니다.
'공유 > JavaScript, TypeScript' 카테고리의 다른 글
[JavaScript] 문자열 반복문 돌리기, 문자열을 배열로 변환하기 (2) | 2022.04.04 |
---|---|
[JavaScript] 배열 원소 swap, 요소 swap (0) | 2022.03.23 |
[JavaScript] promise, callback 지옥 없애기 (0) | 2022.02.24 |
[JavaScript] callback과 callback 지옥 (0) | 2022.02.17 |
[JavaScript] ISO 8601 시간 timestamp로 변환하기 (0) | 2022.02.15 |