도입
ES8 에서는 간단하고 가독성 좋게 비동기 처리를 동기처럼 구현할 수 있도록 async/await 키워드가 도입되었다.
설명
async / await 는 Promise를 기반으로 동작한다.
예시코드
const fetchTodo = async () => {
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const response = await fetch(url);
const todo = await response.json();
console.log(todo);
}
fetchTodo();
await 키워드는 반드시 async 함수 내부에서 사용해야 하며 async 키워드를 사용한 함수는 언제나 Promise를 반환한다(명시적 반환이 없더라도 묵시적으로 Promise를 반환한다)
await 키워드는 Promise가 settled상태가 될 때까지 대기하다가 settled상태가 되면 Promise가 resolve한 결과를 반환한다.

위 예시에서 fetch함수의 동작 중 HTTP요청에 대한 서버의 응답이 도착하고 fetch함수가 반환한 Promise가 settled상태가 되면 Promise가 resolve된 결과를 response변수에 할당하는 것이다.
이처럼 await 키워드는 실행을 일시 중지시켰다가 Promise가 settled상태가 되면 다시 실행을 재개한다.
순차적 처리가 필요없는 개별적 수행이 필요한 비동기 요청의 경우
const foo = async () => {
const res = await Promise.all([
new Promise((resolve) => setTimeout(() => resolve(1), 3000)),
new Promise((resolve) => setTimeout(() => resolve(2), 1000)),
new Promise((resolve) => setTimeout(() => resolve(3), 2000)),
]);
console.log(res);
}
foo();
Promise.all은 내부 요소들이 모두 settled상태가 되면 다음 행을 실행한다.
위 예시의 경우는 각각의 비동기 요청이 서로 연관이 없어서 4초 내로 수행된다.
순차적 처리가 필요한 비동기 요청의 경우
const foo = async () => {
const a = await new Promise((resolve) => setTimeout(() => resolve(1), 3000));
const b = await new Promise((resolve) => setTimeout(() => resolve(2 + a), 2000));
const c = await new Promise((resolve) => setTimeout(() => resolve(3 + b), 1000));
console.log(c);
}
foo();

출력은 7초 이내에 나오는 것을 확인할 수 있다.
에러처리
콜백패턴에서의 에러처리는 호출자방향으로 전파되므로 핸들링하는 것이 힘들다.
async / await는 try / catch문을 통해 에러를 핸들링할 수 있다.
const state = {
loading: false,
}
const fetchTodo = async () => {
state.loading = true;
const url = 'https://jsonplaceholder.typicode.com/todos/1';
try {
const response = await fetch(url);
const todo = await response.json();
console.log(todo);
} catch(e) {
console.error(e);
}
state.loading = false;
}
fetchTodo();
예시 코드에 loading상태를 추가하였다. fetchTodo가 실행되는 동안 state.loading이 true가 되고 fetchTodo가 종료되면 state.loading이 false가 된다.
url로 요청을 실패하는 경우에 대해서 에러메세지를 띄우도록 하였다.

임의로 잘못된 주소를 전달하였다. 정상적으로 console.error가 실행된것을 확인할 수 있다.
만약 fetchTodo함수 내부에서 try / catch를 통해 에러 처리를 하지 않는 다면 fetchTodo는 발생한 에러를 reject하는 Promise를 반환한다.
try / catch를 통해 에러 처리를 하지 않은 경우
const state = {
loading: false,
}
const fetchTodo = async () => {
state.loading = true;
const url = 'https://jsonplaceholdertypicode.com/todos/1';
const response = await fetch(url);
const todo = await response.json();
console.log(todo);
state.loading = false;
}
fetchTodo().then(console.log).catch(console.error);
console.log(state.loading);

위 예시에서 fetchTodo는 발생한 에러를 reject하는 Promise를 반환하며 이후의 행을 실행하지 않아 state.loading값이 true임을 확인할 수 있다. try catch를 통해 에러처리가 필요하다.
'Js' 카테고리의 다른 글
| Js / JavaScript 문법 / difference between strict equality and loose equality (1) | 2025.01.12 |
|---|---|
| JS / javascript / Promise (3) | 2024.12.30 |
| 단축평가(short circuit) (3) | 2023.05.03 |
| 데이터 타입 (3) | 2023.01.04 |
| 표현식과 문 (3) | 2023.01.02 |