아래와 같은 코드가 있을 때, 사용자는 데이터를 불러오는 10초동안 텅 빈 화면을 보게된다.
function fetchUser() {
// do network request in 10 secs....
return 'ming';
}
const user = fetchUser();
console.log(user); // 10초 후에 ming
promise
를 사용하면 아래와 같이 코드를 수정할 수 있다.
function fetchUser() {
return new Promise((resolve, reject) => {
// do network request in 10 secs....
resolve('ming');
});
}
const user = fetchUser();
user.then(console.log);
console.log(user);
위에서 작성된 코드를 promise를 이용하지 않고 비동기 처리할 수 있는 방법이 있는데, 이는 function 앞에 async
를 작성해주는 것이다.
async function fetchUser() {
// do network request in 10 secs....
return 'ming';
}
const user = fetchUser();
user.then(console.log);
console.log(user); // 10초 후에 ming
await
은 async가 붙은 함수 안에서만 사용할 수 있다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000);
return '🍎';
}
async function getBanana () {
await delay(3000);
return '🍌';
}
function pickFruits() {
return getApple().then(apple => {
return getBanana().then(banana => `${apple}+${banana}`);
});
}
pickFruits().then(console.log);
getApple과 getBanana는 3초를 기다렸다가, 사과와 바나나를 리턴하는 함수이다.
이 둘을 더한 pickfruits 함수를 만들어보았는데, Promise문을 중첩적으로 사용하여 콜백 지옥을 연상시킨다.
이를 해결하기 위해 async
와 await
을 사용할 수 있다. (총 소요시간 6초)
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000);
return '🍎';
}
async function getBanana () {
await delay(3000);
return '🍌';
}
async function pickFruits() {
const apple = await getApple();
const banana = await getBanana();
return `${apple}+${banana}`;
}
pickFruits().then(console.log);
에러에 대한 처리는 try-catch
문을 사용하여 할 수 있다.
위에서 작성했던 코드에서 apple과 banana는 서로 연관이 없기 때문에, 서로를 위해 3초씩 기다릴 필요가 없다. 이럴 땐 각각을 병렬적으로 처리해준다. (총 소요시간 3초)
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000);
return '🍎';
}
async function getBanana () {
await delay(3000);
return '🍌';
}
function pickAllFruits() {
return Promise.all([getApple(),getBanana()])
.then(fruits => fruits.join(' + '));
}
pickAllFruits().then(console.log);
Promise.all([])
을 사용하면 배열의 형태로 각각의 Promise를 전달하여 병렬적으로 처리한다.
만일 어떤 것이든 상관없이 먼저 처리되는 것만을 받아오고 싶다면 아래와 같이 promise.race([])
를 사용한다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000);
return '🍎';
}
async function getBanana () {
await delay(2000);
return '🍌';
}
function pickOnlyOne() {
return Promise.race([getApple(),getBanana()]);
}
pickOnlyOne().then(console.log); // 2초만에 수행되는 🍌