Develop/Javascript

async와 await

윤태풍 2021. 2. 24. 21:50

async & await

  • 프로미스 체이닝을 계속 하다보면 코드의 가독성이 떨어짐

  • async 와 await는 Promise를 간결/간편하고 동기적으로 실행되는것 처럼 보이게 만들어주는 API => 그렇다고 무조건 사용하는건 X

  • async 와 await는 기존에 존재하는 Promise 위에 조금 더 간편한 API를 제공함 이런 것을 syntactic sugar 라고 한다 (Class도 해당)

 

1. async

 - 기존 방식

function fetchUser(){
    //do network request in 10s..
    return new Promise((resolve, reject)=>{
        //return 'dada';  > promise가 pending 상태로 남아있게된다. 
        //***** executor 함수 안에선 꼭 resolve나 reject의 상태를 지정해줘야함 **********
        resolve('dada');  // promise fullfiled 상태
        // reject(new Error(`error`)); > 프로미스 rejected 상태
    });
}    //동기적으로 코드 수행하므로 10초동안 머물러서 기다리지 않게 하려 promise를 사용

- async 사용시 (내가 안써도 함수의 코드블록이 자동으로 Promise로 변환됨)

// 함수 선언식
async function fetchUser() {
  return `dada`;
}

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

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

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

 

2. await

 - 기존 방식

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));

==> chaining도 중첩적으로 많이 사용하게 되면 콜백지옥 비슷한걸 경험할수 있어😩😩

 

 - await 사용시

  • await는 async함수 내부에서만 사용가능
  • 위의 방식처럼 chaining 하던 것을 동기적으로 쓰는 것처럼 await를 사용해 이해하기 쉽게 만들어 줄 수 있음
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 `🍌`;
}

 - try catch 로 error 처리 가능

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}`;
    apple과 banana는 서로 연관 없으므로 기다려줄 필요가 없음 밑에처럼 개선 가능
    */
    // 위는 순차적인 실행 밑에는 병렬실행

   const applePromise = getApple();
   const bananaPromise = getBanana();      // 이때 만들자마자 바로 실행 (병렬실행 가능)
   const apple = await applePromise();
   const banana = await bananaPromise();
   return `${apple} + ${banana}`;
 }

pickFruits().then(console.log);

 

3. 유용한 Promise API

: 병령실행시 위의 코드는 좀 더러우므로 제공되는 Promise의 API로 깔끔하게 정리 O

function pickAllFruits(){
    return Promise.all([getApple(), getBanana()]) 
    .then(fruits => fruits.join('+'));
} 
//all을 써서 배열형태로 (getApple()..)전달->이 배열들의 것들을 다 받아서 배열로 다시 줌(fruit==> 'apple','banana')

//뽀너스) 배열에 있는 것들중 가장 먼저 도착하는 놈을 return
function pickOnlyOne(){
    return Promise.race([getApple(), getBanana()]);
}