250x250
Notice
Recent Posts
Recent Comments
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

진스

12. async / await 본문

JavaScript

12. async / await

입방정 2021. 4. 9. 17:49
728x90

async & await

  • 프로미스 체이닝을 계속 하다보면 코드의 가독성이 떨어짐
  • async 와 await는 Promise를 간결/간편하고 동기적으로 실행되는것 처럼 보이게 만들어주는 API
  • async 와 await는 새로운 것이 추가 된게 아니라, 기존에 존재하는 Promise 위에 조금 더 간편한 API를 제공함 이런 것을 syntactic sugar 라고 한다 (Class도 마찬가지..)

비동기 처리를 반드시 해야하는 이유

  • JS 엔진은 블록({})안에 코드를 동기적으로 실행(처리) 함
  • 시간이 오래 걸리는 코드를 비동기 처리를 전혀 하지 않으면, 다음 코드에 문제가 발생할 수 있음
  • 예를 들어 서버에서 data를 받아와서 웹페이지에 출력하는 시나리오가 있다
  • data를 받아 오는데 10초가 걸림, 근데 비동기 처리를 안하면 텅 빈 data를 출력 해버림
  • Promise 상황극: 내가 언제 유저의 data를 받아 올진 모르겠지만 내가 약속할께, Promise라는 object를 가지고 있으면, 여기에 니가 then 이라는 콜백함수만 등록해 놓으면, 유저의 data가 준비 되는대로 니가 등록한 콜백함수를 불러줄께

1. async

1.1 기존 방식(Promise)

// 프로미스를 사용하면 반드시 resolve와 reject를 호출해야 함
function fetchUser() {
  return new Promise((resolve, reject) => {
    // return `ellie`; // 프로미스 pending 상태
        resolve(`ellie`); // 프로미스 fulfilled 상태
        // reject(new Error(`error`)); // 프로미스 rejected 상태
  });
}

const user = fetchUser();
// console.log(user);
user.then(user => console.log(user));

1.2 async 사용

  • async를 사용하면 함수의 코드 블록이 자동으로 Promise로 변환이 되어짐 (대박!)
// 1. 함수 선언식
async function fetchUser() {
  return `ellie`;
}

// 2. 함수 표현식
const fetchUser = async function() {
  return `ellie`;
};

// 3. 화살표 함수
const fetchUser = async () => {
  return `ellie`;
};

// fetchUser().then(data => console.log(data)); // 함수로 바로 호출
const user = fetchUser(); // 변수에 할당해서 호출
user.then(data => console.log(data));
console.log(user);

2. await

2.1 기존 방식(Promise)

  • 콜백 지옥이 떠오름..
function delay(ms) {
  return new Promise (resolve => setTimeout(resolve, ms));
}

function getApple() {
  return delay(1000)
  .then(() => `🍎`);
}
function getBanana() {
  return delay(1000)
  .then(() => `🍌`);
}

function pickFruits() {
  return getApple()
  .then(apple => {
    return getBanana().then(banana => `${apple} + ${banana}`);
  });
}
pickFruits().then(result => console.log(result));

2.2 await 사용 (error 처리: try/catch문)

  • await는 async 함수 내부에만 사용 가능
  • getApple과 getBanana는 서로 독립적인 코드인데 순차적으로 실행됨 → 비효율
function delay(ms) {
  return new Promise (resolve => setTimeout(resolve, ms));
}

async function getApple() {
  await delay(1000);
  // throw new Error(`error: apple`); // error 발생
  return `🍎`;
}
async function getBanana() {
  await delay(1000);
  // throw new Error(`error: banana`);
  return `🍌`;
}

async function pickFruits() {
  let apple = null;
  try {
    apple = await getApple();
  } catch(error) {
    console.log(error);
  }
  let banana = null;
  try {
    banana = await getBanana();
  } catch(error) {
    console.log(error);
  }
  return `${apple} + ${banana}`;
}
pickFruits().then(result => console.log(result));

2.3 await 병렬 처리

function delay(ms) {
  return new Promise (resolve => setTimeout(resolve, ms));
}

async function getApple() {
  await delay(1000);
  return `🍎`;
}
async function getBanana() {
  await delay(1000);
  return `🍌`;
}

// 방법 1: 무식한 코드
async function pickFruits() {
  // 프로미스 객체는 선언 즉시 바로 실행됨
  // getApple과 getBanana는 병렬(독립적)로 실행됨
  const applePromise = getApple();
  const bananaPromise = getBanana();
  // 동기화
  const apple = await applePromise; 
  const banana = await bananaPromise;
  return `${apple} + ${banana}`;
}
pickFruits().then(result => console.log(result));

// 방법 2: Promise APIs 사용
function pickAllFruits() {
  return Promise.all([getApple(), getBanana()]).then(fruits => {
    return fruits.join(` + `);
  });
    // return Promise.all([getApple(), getBanana()]);
}
pickAllFruits().then(console.log);

// 번외: 비동기 처리중 먼저 리턴하는 녀석만 출력
function pickOnlyOne() {
  return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log);
728x90

'JavaScript' 카테고리의 다른 글

ssr (서버 사이드 랜더링) csr (클라이언트 사이드 랜더링)차이  (0) 2021.04.24
웹에서 다크 모드로 토글 (css 변수 이용)  (0) 2021.04.14
11. Promise  (0) 2021.04.09
10. Callback 지옥  (0) 2021.04.09
9. JSON  (0) 2021.04.09
Comments