→ clear style of using promise
→ Promise를 좀 더 간결하고 간편하면서 동기적으로 실행 되는 것 처럼 보이게 만들어 주는 것.
→ Promise를 여러개 사용하면 코드가 난잡해지는데, 체이닝이 된 여러개의 Promise 위에 좀 더 간편한 API로 async와 await을 사용하면, 동기식으로 코드를 순서대로 작성하는 것 처럼 간편하게 작성하는 것을 도와줌.
: 기존에 존재하는 것 위에 혹은 기존에 존재하는 것을 감싸서 간편하게 사용 가능한 API를 제공하는 것을.(ex. class: prototype을 베이스로 한 그 위에 실짝 덧붙여진 syntactic sugar)
function fetchUser() {
// do network request in 10 secs...
return 'YunTroll';
}
const user = fetchUser(); // 바로호출
console.log(user);
무언가 오래 걸리는 코드를 비동기적인 처리를 전혀안하면, JavaScript 엔진은 동기적으로 코드를 수행 →즉, 한줄이 끝나야 넘어가는 동기적인 처리를 함!
그래서 위의 코드를 보면const user = fetchUser()
가 호출 →function fetchUser()
함수가 선언된 곳으로 가서 함수의 코드 블럭을 실행 →do network request in 10 secs...
그리고 실행되는데 10초가 걸리기 때문에 끝날때까지 10초간 머무르고 있음 → 10초가 지나서 성공적으로 network에서 데이터를 받아오면 그 후에return 'YunTroll' 실행
→ 그리고 return된 코드가 user에 할당이 되고 →console.log
실행
: 여기서 비동기 처리를 하지 않으면 사용자 데이터를 받아오는데 10초가 걸리기 때문에, 만약 뒤에 웹페이지를 표시하는 UI기능의 코드가 있다면, fetchUser를 받아오기 전에 데이터가 웹에 표시 되지 않음 → 사용자는 10초정도 텅텅빈 웹페이지를 보고 있게 됨
그래서! 이렇게 오래걸리는 일들은 비동기적으로 처리를 해야함
Promise는
Promise
오브젝트를 가지고 있으면, 여기에then
라는 callback 함수만 등록해 놓으면 user의 데이터가 준비되는대로 등록한 callback 함수를 불러줌
→ Promise는 resolve나 reject를 사용하지 않으면 상태가pending
결과는undefined
나옴. 그래서 꼭! resolve와 reject를 사용해야함
async function fetchUser() {
// do network request in 10 secs...
return 'YunTroll';
}
// 이렇게 사용하면 번거롭게 Promise를 사용하지 않아도, 자동으로 함수 내부의 코드블럭들이 Promise로 변환됨
const user = fetchUser();
user.then(console.log)
console.log(user);
// 결과값: Promise {<fullfilled>: "YunTroll"}
// YunTroll
fetchUser가 바로 Promise를 return함!
async
와await
는 Promise를 감싸고 있는, Promise를 간편하게 사용할 수 있는syntactic sugar
라서 바로 Promise로 만들 수 있음
: await
는 async
키워드가 붙은 함수 내에서만 사용 가능
function delay(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
// delay 함수는 Promise를 return 함.
// 정해진 ms가 지나면 resolve를 호출함
async function getApple() {
await delay(3000); // await를 사용하게 되면 delay가 끝날때까지 기다려줌!
return '🍎'; // 3초 후에 🍎 return 하는 Promise가 만들어짐
}
async function getBanana() { // 다시 Promise를 만듬
await delay(3000); // 3초 후에
return '🍌'; // 🍌 return
}
// 사과와 바나나를 전부 가져오는 함수를 Promise로 만들면?
function pickFruits() {
return getApple().then(apple => {
return getBanana()
.then(banana => `${apple} + ${banana}`);
});
}
pickFruits().then(console.log);
// 결과: 6초 기다린 후 콘솔창에 🍎 + 🍌
// Promise도 이렇게 중첩적으로 작성하면 또 콜백지옥 댐!
// 사과와 바나나를 전부 가져오는 함수를 async로 만들면?
async function pickFruits() {
const apple = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
// 결과: 6초 기다린 후 콘솔창에 🍎 + 🍌
async
와await
를 사용해서 자연스럽게 코드를 작성하는것 처럼 쓰기 때문에 간폄함!
: await
는 async
키워드가 붙은 함수 내에서만 사용 가능
function delay(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(3000);
throw 'error';
return '🍎';
}
async function getBanana() {
await delay(3000);
throw 'error';
return '🍌';
}
// 기존에 에러핸들링 하는것 처럼 try, catch 활용!
async function pickFruits() {
const apple = await getApple(); // 사과를 받는데 기다리고(3초 지남)
const banana = await getBanana(); // 바나나 받는데 기다리고(3초 지남)
// 사과와 바나나를 받는데 서로 연관이 안되어 있음, 그래서 서로 기다릴 필요 ❌
return `${apple} + ${banana}`;
}
// 그래서 이런 문제를 해결하면 ↓
async function pickFruits() {
const applePromise = getApple(); // Promise를 만드는 순간 바로 Promise 내부의 코드 블럭이 실행 됨
const bananaPromise = getBanana();
const apple = await applePromise;
const banana = await bananaPromise;
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
// 결과: 3초만에 콘솔창에 🍎 + 🍌 나옴
// 병렬적으로 처리했기때문에 사과와 바나나를 동시에 가져와서 한번에 기다렸다가 출력!
function pickAllFruits() {
return Promise.all([getApple(), getBanana()])
// 배열형태로 getApple의 Promise의 배열과 getBanana의 Promise의 배열을 전달
.then(fruits => fruits.join(' + ')
// 다 받아진 배열이 다시 전달 → 그리고 배열을 string으로 묶을 수 있는 join을 활용
);
}
pockAllFruits().then(console.log);
// 결과: 3초만에 콘솔창에 🍎 + 🍌 나옴
위와 같이 병렬구조인 경우 Prormise에 있는
all
api를 사용.
Promise배열
전달 시, 모든 Promise들이 병렬적으로 다 받을때까지 모아주는 함수
// 어떤거든 상관없이 먼저 따지는 첫 번째 과일만 가져오고 싶으면?
async function getApple() {
await delay(3000);
throw 'error';
return '🍎';
}
async function getBanana() {
await delay(1000);
throw 'error';
return '🍌';
}
function pickOnlyOne() {
return Promise.race([getApple(), getBanana()]);
// 배열에 전달 된 Promise 중에서 가장 먼저 값을 return하는것만 전달
}
pickOnlyOne().then(console.log);
// 결과: 🍌