클론 프로젝트를 하면서 async
, await
를 사용했었는데, 정확히 프라미스의 .then
메서드를 사용하는 것과 어떻게 다른지 이해 없이 그냥 외워서 썼다. 항상 찝찝함이 남아있었는데, 이번 기회에 에이싱크 어웨이트 완전히 뿌셔보리라....... 💥💥💥
나의 최애 멘토님에게 배웠습니다 🎄
Mastering Async/Await 번역문 시리즈
async
async
는 function 앞에 위치하는데, 해당 함수는 항상 프라미스를 반환한다.
문법
async function f() {
return 1;
}
프라미스가 아닌 값을 반환하더라도 resolved promise로 값을 감싸 이행된 프라미스가 반환되게 한다. 따라서 아래 두개의 함수는 동일한 프라미스가 반환된다.
async function f() {
return 1;
}
f().then(alert); // 1
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
async
는 반드시 프라미스를 반환한다! 프라미스가 아닌 것은 프라미스로 감싸서 반환한다! so simple! ^0^await
문법
// await는 async 함수 안에서만 동작합니다.
let value = await promise;
자바스크립트는 await
키워드를 만나면 프라미스가 처리될 때까지 기다린다.
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)
alert(result); // "완료!"
}
f();
이름처럼 실행이 잠시 '중단' 되었다가 프라미스가 처리되면 실행이 재개된다. 프라미스가 처리되길 기다리는 동안에 엔진이 다른 일(다른 스크립트 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않는다.
await
사용 불가! Error 발생!await
는 최상위 레벨 코드에서 작동하지 않는다.// 최상위 레벨 코드에선 문법 에러가 발생함
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
익명 async 함수로 코드를 감싸면 최상위 레벨 코드에서도 사용할 수 있다.
(async () => {
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
...
})();
async
를 추가하면 async 클래스 메서드를 선언할 수 있다.class Waiter {
async wait() {
return await Promise.resolve(1);
}
}
new Waiter()
.wait()
.then(alert); // 1
async
메서드와 async
함수는 프라미스를 반환하고 await
를 사용할 수 있다는 점에서 동일하다.
프라미스가 거부되면 throw
문을 작성한 것처럼 에러가 던져진다. 아래 두 코드는 동일하다.
async function f() {
await Promise.reject(new Error("에러 발생!"));
}
async function f() {
throw new Error("에러 발생!");
}
await
가 던진 에러는 try...catch
를 사용해 잡을 수 있다. try
안에는 여러 줄의 코드를 감쌀 수 있다.
async function f() {
try {
let response = await fetch('http://유효하지-않은-url');
let user = await response.json();
} catch(err) {
// fetch와 response.json에서 발행한 에러 모두를 여기서 잡습니다.
alert(err);
}
}
f();
try...catch
가 없으면 async 함수를 호출해 만든 프라미스가 거부된 상태가 된다. .catch
를 추가하면 거부된 프라미스를 처리할 수 있지만, 추가하는 것을 잊으면 프라미스 에러가 발생한다.
async/await
를 Promise.all
과 함께 사용하기// 프라미스 처리 결과가 담긴 배열을 기다립니다.
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]);