es8에서는 제너레이터보다 간단하고 가독성 좋게 비동기처리를 동기 처리처럼 동작하도록 구현할 수 있는 async/await이 도입되었다.
async 함수는 async 키워드를 사용해 정의하며 언제나 프로미스를 반환한다.
async & await : 깔끔하게 promise를 사용하는 방법
무조건 async & await >> promise가 아니라 경우에 따라 더 좋은 게 있다.
function fetchUser() {
return new Promise((resolve, reject) => {
resolve("ellie");
});
}
const user = fetchUser();
user.then(console.log);
async function fetchUser() {
return "ellie";
}
const user = fetchUser();
user.then(console.log);
await 키워드는 settled 상태(비동기 처리가 수행된 상태)가 될 때까지 대기하다가 settled 상태가 되면 프로미스가 resolve한 처리 결과를 반환한다.
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function getApple() {
await delay(1000);
return "🍎";
}
async function getBanana() {
await delay(1000);
return "🍌";
}
function getBanana() {
return delay(1000).then(() => "🍌");
}
예를 들어 사과를 받고, 사과가 받아오지면 바나나를 받고, 바나나가 받아와지면 사과랑 바나나를 묶어서 리턴하는 상황을 설정해보자. 🍎 + 🍌
function pickFruits() {
return getApple().then((apple) => {
return getBanana().then((banana) => `${apple}+${banana}`);
});
}
async function pickFruits() {
const apple = await getApple(); // 1초 소요
const banana = await getBanana(); // 1초 소요
return `${apple} + ${banana}`; // 2초 소요
}
pickFruits().then(console.log); // 🍎 + 🍌
async/await에서 에러 처리는 try..catch문을 사용할 수 있다.
프로미스를 반환하는 비동기 함수는 명시적으로 호출할 수 있기 때문에 호출자가 명확하다.
async function getBanana() {
await delay(1000);
throw "에러 발생";
return "🍌";
}
async function pickFruits() {
try {
const apple = await getApple();
const banana = await getBanana();
} catch (err) {
console.log(err);
}
return `${apple} + ${banana}`;
}
서로 연관없이 개별적으로 수행되는 비동기 처리이기 때문에, 앞선 비동기 처리가 완료될 때까지 대기해서 순차적으로 처리할 필요가 없다.
async function pickFruits() {
const apple = await getApple(); // 1초 소요
const banana = await getBanana(); // 1초 소요
return `${apple} + ${banana}`; //총 2초 소요
}
pickFruits().then(console.log); // 🍎 + 🍌
async function bar(n) {
const 과일 = await new Promise((resolve) =>
setTimeout(() => resolve(n), 3000)
);
const 과일잼 = await new Promise((resolve) =>
setTimeout(() => resolve(과일 + 잼), <3000)
);
const 과일잼토스트 = await new Promise((resolve) =>
setTimeout(() => resolve(과일잼 + 토스트), 3000)
);
return 과일잼토스트;
}
bar(사과);
사과를 따서 사과잼을 만들어서 사과잼 토스트 먹을 게 아니라면(서로 연관 없이 개별적으로 수행해도 되면) 병렬 처리한다.
function pickAllFruits() {
return Promise.all([getApple(), getBanana()]).then((fruitsArray) =>
fruitsArray.join("+")
);
}
pickFruits().then(console.log); // "🍎 + 🍌"
function pickOnlyOne() {
return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log); //🍌 1초만에 출력
요약하자면 async, await은 promise를 간편하게 쓸 수 있고, promise는 all이나 race처럼 유용한 api가 있다.
자세한 정리 감사합니다~~