async/await
- ES8에 도입된 async/await은 Promise를 기반으로 동작하여 가독성 좋게 비동기 처리를 동기처럼 보이도록 구현할 수 있습니다.
async/await 사용법
const fetchTodo = async () => {
const res = await fetch(url);
const todo = await res.json();
console.log(todo);
};
fetchTodo();
- 위와 같이 Promise의 then과 같은 후속 처리 메서드를 호출할 필요없이 마치 동기처럼 보이도록 구현할 수 있습니다.
async 함수
async function foo(n) {
return n;
}
foo(1).then((res) => console.log(res)); // return 1
const bar = async function (n) {
return n;
};
bar(2).then((res) => console.log(res)); // return 2
const baz = async (n) => n;
baz(3).then((res) => console.log(res)); // return 3
const obj = {
async foo(n) {
return n;
},
};
obj.foo(4).then((res) => console.log(res));
class MyClass {
async bar(n) {
return n;
}
}
const myClass = new MyClass();
myClass.bar(5).then((res) => console.log(res));
- await 키워드는 반드시 async 함수 내부에서 사용해야 합니다. async 함수는 async 키워드를 사용해 정의하며 언제나 프로미스를 반환합니다. async 함수가 명시적으로 프로미스를 반환하지 않더라도 async 함수는 암묵적으로 반환값을 resolve하는 프로미스를 반환합니다.
- 클래스의 constructor 메서드는 async 메서드가 될수 없습니다. 클래스의 constructor 메서드는 인스턴스를 반환해야 하지만 async 함수는 언제나 프로미스를 반환해야 하기 때문입니다.
await 키워드
(async () => {
const res = await fetch(url);
console.log(res.status);
})();
- await 키워드는 Promise가 settled 상태(비동기 처리가 수행된 상태)가 될 때까지 대기하다가 settled 상태가 되면 Promise가 resolve한 처리 결과를 반환합니다. await 키워드는 반드시 Promise 앞에 사용해야 합니다.
await 키워드 사용시 주의할 점
const foo = async () => {
const a = await new Promise((resolve) => setTimeout(() => resolve(1), 3000));
const b = await new Promise((resolve) => setTimeout(() => resolve(2), 1000));
const c = await new Promise((resolve) => setTimeout(() => resolve(3), 1000));
console.log("Hello Wolrd");
};
// 약 6초 소요
foo();
console.log("finish");
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), 1000)),
]);
console.log(res);
};
// 약 3초 소요
foo();
console.log("finish");
- foo 함수를 호출할 경우 await으로 인해 6초 이후 "Hello World"가 출력됩니다. 즉, 위와 같이 각각의 Promise가 서로 연관되지 않고 처리 순서를 지킬 필요가 없다면은 일일이 await을 거는 것보다는 Promise.all을 이용해서 한번에 요청 후 요청한 비동기 요청이 완료되었을 때 응답을 처리하는 것이 좋습니다.
에러 핸들링
(async () => {
try {
const res = await fetch(url);
} catch (err) {
console.log(err);
}
})();
- Prmoise를 후속 처리 메서드로 처리할 경우 try/catch로 에러 핸들링하기 적합하지 않습니다. 하지만, async/await에서 에러 처리는 try/catch를 사용하기에 적합합니다.
- async 함수 내에서 err가 발생되었을 경우 에러를 reject하는 Promise를 반환합니다. 그렇기 때문에 async 함수 외부에서 .catch 후속 처리 메서드로 에러를 핸들링 할 수 있습니다.