개발자공부일기
async/await 본문
async/await를 쓰는 이유
자바스크립트에는 비동기 처리 방식이 3가지가 있는데 콜백 함수와 이를 개선한 Promise객체 그리고 async/await가 있다.
콜백 함수를 사용하면 Callback Hell에 빠지기 쉽고 이를 개선한 Promise도 무분별한 then의 사용으로 Promise Hell에 빠지는 상황이 생긴다.
Callback Hell
step1(function (value1) {
step2(function (value2) {
step3(function (value3) {
step4(function (value4) {
step5(function (value5) {
step6(function (value6) {
// Do something with value6
});
});
});
});
});
});
Promise Hell
fetch('https://example.com/api')
.then(response => response.json())
.then(data => fetch(`https://example.com/api/${data.id}`))
.then(response => response.json())
.then(data => fetch(`https://example.com/api/${data.id}/details`))
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
둘 다 무슨 작업인지 한 번에 알아보기가 힘든데 그래서 우린 async와 await를 사용한다.
async function getData() {
const response = await fetch('https://example.com/api');
const data = await response.json();
const response2 = await fetch(`https://example.com/api/${data.id}`);
const data2 = await response2.json();
const response3 = await fetch(`https://example.com/api/${data.id}/details`);
const data3 = await response3.json();
console.log(data3);
}
getData();
좀더 보기가 편해졌다.
기억해야 할 점이 async/await가 Promise를 대체하기 위한 기능이 아니라는 것이다. 내부적으로는 여전히 Promise를 사용해서 비동기를 처리하고, 단지 코드 작성 부분을 프로그래머가 유지보수하게 편하게 보이는 문법만 다르게 해줄 뿐이라는 것이다.
async/await의 사용법
function 앞에 async를 붙이고 비동기로 처리하는 부분 앞에 await를 붙이면 된다.
function resolveAfter2Seconds() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
// Expected output: "resolved"
}
asyncCall();
/*
출력
"calling"
"resolved"
*/
보시다시피 await가 붙은 resolveAfter2Seconds가 완료될때까지(2초후) 기다리고 result 로그를 띄웁니다.
그리고 async가 붙은 함수의 리턴값은 Promise객체다. resolved가 출력되는걸 볼 수 있다. 그렇다는 말은 .then()도 쓸 수 있다. 하지만 난 안쓸거다.
async/await 에러 처리
function resolveAfter2Seconds() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
try {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
// Expected output: "resolved"
} catch (err) {
console.error(err);
}
}
asyncCall();
/*
출력
"calling"
"resolved"
*/
그냥 async함수 안에 try catch로 감싸서 오류를 잡아내면 된다.
생각해봐야 할 것
await는 작업이 완료되기 전까지 대기하는 것이기 때문에 A,B가 a라는 데이터에 접근한다면 필요하겠지만
A는 a에 B는 b에 접근하고있다면 await를 쓰는게 손해가 될 수 있다. 물론 A는 a에 B는 b에 접근하고 있더라도 await를
사용해야할 경우가 있을 수 있는데,
async function getFruites(){
let getApplePromise = getApple(); // async함수를 미리 논블록킹으로 실행한다.
let getBananaPromise = getBanana(); // async함수를 미리 논블록킹으로 실행한다.
// 이렇게 하면 각각 백단에서 독립적으로 거의 동시에 실행되게 된다.
console.log(getApplePromise)
console.log(getBananaPromise)
let a = await getApplePromise; // 위에서 받은 프로미스객체 결과 변수를 await을 통해 꺼낸다.
let b = await getBananaPromise; // 위에서 받은 프로미스객체 결과 변수를 await을 통해 꺼낸다.
console.log(`${a} and ${b}`); // 본래라면 1초+1초 를 기다려야 하는데, 위에서 1초기다리는 함수를 바로 연속으로 비동기로 불려왔기 때문에, 대충 1.01초만 기다리면 처리된다.
})
이런식으로 이미 받아온 변수를 꺼낼때만 await하도록 분리해두면 쓸 수 있다.
'Javascript' 카테고리의 다른 글
Express (0) | 2025.02.07 |
---|---|
Arrow Function(화살표 함수) (0) | 2025.02.05 |
Promise (0) | 2025.02.04 |
var, let ,const의 차이 그리고 변수 호이스팅 (0) | 2025.02.04 |
Promise와 forEach의 동작 차이 (0) | 2024.12.31 |