티스토리 뷰

이번에는 async/await를 알아보겠습니다.

비동기 처리, callback 함수와 promise가 낯설다 하시면 아래의 포스팅 먼저 보고 오시면 됩니다😊

 

동기/비동기, callback 함수👇

https://hiolivia.tistory.com/42

promise란?👇

https://hiolivia.tistory.com/46

 

지금까지 살펴본 비동기처리 방식은 이러했습니다.

//함수선언식&화살표함수
const ex1 = () => 
  new Promise((resolve, reject) => {
    let name = "olly";
    resolve(name);
  });
ex1().then(console.log); //olly

//ex1().then((name)=>console.log(name))
//= ex1().then(console.log);
//argument가 같을 때에는 (argument)생략 가능
	
//함수표현식
function ex2() {
  return new Promise((resolve, reject) => {
    let name = "olly";
    resolve(name);
  });
}
ex2().then(console.log); //olly

 

async는 함수 처리 방식을 더 간단하게 만들어주는데요, 위의 코드를 재사용해보겠습니다.

async function ex3{
  let name = "olly";
  return name;
}
ex3().then(console.log); //olly

함수 앞에 async 키위드를 붙여주면 자동으로 해당 함수가 promise로 바뀝니다. 여기서 헷갈릴 수 있는건 데이터를 resolve 함수가 아닌 return을 사용해 전달해주는 것입니다. 이처럼 async를 사용하면 적은 양의 코드로 promise를 간단하게 사용할 수 있습니다.

 

다음은 await를 사용해보겠습니다. 간단히 말하자면 'promise의 실행이 끝날 때까지 기다려!' 하는 것인데요, async function 안에서만 사용할 수 있습니다. 간단한 예제에서 확인해보세요.

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

//await을 사용했을 때
async function result() {
  await delay();
  return 'Hi!';
}

//then()을 사용했을 때
function result(){
  delay().then(()=>'Hi!');
}

//결과
result().then((data) => console.log(data)); //Hi!

delay() 함수가 실행된 다음, 3초 후에 Hi를 출력하는 것을 볼 수 있습니다. 여기서 await을 사용하는 이유는 코드가 마치 동기적으로 움직이는 것처럼 보이기 때문에 가독성이 좋다는 장점이 있습니다.

 

Promise 포스팅에서 사용했던 예제를 다시 사용해보겠습니다.

//promise&then 사용 예제

const getHen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve("🐓"), 1000);
  });
const getEgg = (hen) =>
  new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000);
  });
const cook = (egg) =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => 🍳`), 1000);
  });
  
getHen()
  .then((hen) => getEgg(hen))
  .catch((error) => {
    return "🍌";
  })
  .then((egg) => cook(egg))
  .then((meal) => console.log(meal));
  
  
  //에러가 없었으면
  //🐓 => 🥚 => 🍳
  
  //실행결과
  //🍌 => 🍳

이 예제를 async/await을 사용해 다시 작성해보겠습니다.

//async&await 예제

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

async function getHen() {
  await delay();
  return "🐓";
}

async function getEgg() {
  await delay();
  return "🥚";
}

async function getMeal() {
  await delay();
  return "🍳";
}

async function result() {
  const hen = await getHen();
  const egg = await getEgg();
  const meal = await getMeal();
  return `${hen}=>${egg}=>${meal}`;
}

result().then(console.log); //🐓=>🥚=>🍳

이렇게 마치 동기적으로 작동하는 것처럼 코드를 작성했기 때문에 훨씬 더 알아보기 쉽고 간단하지 않나요?👏

 

하지만 여기서 한 가지 문제점이 발생합니다.

3개의 함수에서 🐓,🥚,🍳의 데이터를 가져오는 데 각각 2초씩, 총 6초나 걸립니다. 비동기 방식의 단점이 한꺼번에 여러 개의 작업을 수행한다는 것이었죠? 이렇게 되면 동기식과 다름이 없습니다. 

모든 데이터를 2초만에 가져오도록 병렬 작업을 해주겠습니다. result() 함수만 수정해주면 됩니다.

async function result() {
  const waitforhen = getHen();
  const waitforegg = getEgg();
  const waitformeal = getMeal();
  const hen = await waitforhen;
  const egg = await waitforegg;
  const meal = await waitformeal;
  return `${hen}=>${egg}=>${meal}`;
}

이렇게 수정해주면 2초만에 🐓=>🥚=>🍳를 출력하는 것을 볼 수 있습니다.

 

마지막으로 에러 핸들링을 해보겠습니다. 원래의 코드에는 🐓=>🥚=>🍳을 가져오는 것을 시도했지만 중간에 에러가 발생했습니다. 이 부분을 async를 사용해 구현해봅시다.

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

    async function getHen() {
      await delay();
      return "🐓";
    }

    async function getEgg() {
      await delay();
      throw "error";
      return "🥚";
    }

    async function getMeal() {
      await delay();
      return "🍳";
    }

    async function result() {
      try {
        const waitforhen = getHen();
        const waitforegg = getEgg();
        const waitformeal = getMeal();
        const hen = await waitforhen;
        const egg = await waitforegg;
        const meal = await waitformeal;
        return `${hen}=>${egg}=>${meal}`;
      } catch {
        return "🍌";
      }
    }

    result().then(console.log);

요리를 하는 과정에서 에러가 발생하면 바나나를 리턴합니다. 동기식/비동기식 동일하게 try, catch 구문을 쓸 수 있다는 것도 장점입니다.

 

*정리*

1. promise가 실행되는 함수는 async 키워드를 사용해 함수를 선언한다.

2. async 키워드를 사용해 선언된 함수는 resolve 대신 return을 사용해 데이터를 반환한다.

3. await는 promise 실행이 완료될 때까지 기다리라는 의미이고, async 함수 안에서만 사용가능하다.

4. await는 then()을 대체한다.