[20220807_async & await]

YunTrollpark·2022년 8월 7일
0

JavaScript

목록 보기
2/2

async & await

→ clear style of using promise
→ Promise를 좀 더 간결하고 간편하면서 동기적으로 실행 되는 것 처럼 보이게 만들어 주는 것.
→ Promise를 여러개 사용하면 코드가 난잡해지는데, 체이닝이 된 여러개의 Promise 위에 좀 더 간편한 API로 async와 await을 사용하면, 동기식으로 코드를 순서대로 작성하는 것 처럼 간편하게 작성하는 것을 도와줌.

syntactic sugar

: 기존에 존재하는 것 위에 혹은 기존에 존재하는 것을 감싸서 간편하게 사용 가능한 API를 제공하는 것을.(ex. class: prototype을 베이스로 한 그 위에 실짝 덧붙여진 syntactic sugar)

1. async

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함!
asyncawait는 Promise를 감싸고 있는, Promise를 간편하게 사용할 수 있는 syntactic sugar라서 바로 Promise로 만들 수 있음

2. await

: awaitasync 키워드가 붙은 함수 내에서만 사용 가능

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초 기다린 후 콘솔창에 🍎 + 🍌

asyncawait를 사용해서 자연스럽게 코드를 작성하는것 처럼 쓰기 때문에 간폄함!

3. 병렬처리

: awaitasync 키워드가 붙은 함수 내에서만 사용 가능

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초만에 콘솔창에 🍎 + 🍌 나옴
// 병렬적으로 처리했기때문에 사과와 바나나를 동시에 가져와서 한번에 기다렸다가 출력!

4. 병렬처리 깔끔하게 작성하기

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);
// 결과: 🍌
profile
코딩으로 세상에 이야기하는 개발자

0개의 댓글