이 글은 『자바스크립트 딥 다이브』를 공부하며 정리한 내용입니다.
ES8(ECMAScript 2017)에서 도입된 async/await는 프로미스를 기반으로 하며, 비동기 코드를 마치 동기 코드처럼 작성할 수 있게 해주는 문법이다.
기존에는 비동기 처리 후속 작업을 then, catch에 콜백 형태로 전달해야 했지만 async/await를 사용하면 후속 처리 메서드 없이 자연스러운 흐름으로 비동기 코드를 작성할 수 있다.
// async 함수 선언문
async function foo(n) {return n};
foo(1).then(v => console.log(v)); // 1
// async 함수 표현식
const bar = async function(n) {return n};
bar(2).then(v => console.log(v)); // 2
// async 화살표 함수
const baz = async n => n;
baz(3).then(v => console.log(v)); // 3
// async 메서드
const obj = {
async foo (n) {return n};
};
obj.foo(4).then(v => console.log(v)); // 4
// async 클래스 메서드
class MyClass {
async bar (n) {return n};
}
const myClass = new MyClass();
myClass.bar(5).then(v => console.log(v)); //
모든 비동기 처리에 await를 걸면 불필요한 “순차 실행”이 일어난다.
async function foo() {
const res = awite Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)),
new Promise(resolve => setTimeout(() => resolve(2), 2000)),
new Promise(resolve => setTimeout(() => resolve(3), 1000)),
]);
console.log(res); // [1, 2, 3]
}
foo();
async function foo() {
const a = await new Promise(resolve => setTimeout(() => resolve(1), 3000));
const b = await new Promise(resolve => setTimeout(() => resolve(a + 1), 2000));
const c = await new Promise(resolve => setTimeout(() => resolve(b + 1), 1000));
console.log(res); // [1, 2, 3]
}
foo();
이처럼 앞선 결과가 다음 로직에 필요하다면 순차 실행해야 한다.
async/await에서는 try ... catch를 사용해 동기 코드와 동일한 방식으로 에러를 처리할 수 있다.
const foo = async () => {
try {
const wrongUrl = 'https://wrong.url';
const res = await fetch(wrongUrl);
const data = await res.json();
console.log(data);
} catch(err) {
console.log(err);
}
};
foo()
try 블록 내부에서 발생한 모든 에러(네트워크 에러 포함)를 catch가 잡는다.
또한 async 함수에서 catch를 생략하면, 해당 async 함수는 reject 상태의 프로미스를 반환하기 때문에 .catch() 메서드로 에러 처리도 가능하다.
const foo = async () => {
const wrongUrl = 'https://wrong.url';
const res = await fetch(wrongUrl);
const data = await res.json();
return data;
};
foo().then(console.log).catch(console.error);