ES2017의 새로운 기능: async와 await

DaiVernon·2021년 7월 25일
0

JavaScript

목록 보기
8/10
post-thumbnail

이 글은 알베르토 몬탈레시의 모던 자바스크립트 핵심 가이드를 기반으로 작성되었습니다.


ES2017에서는 async/await 키워드를 이용한 새로운 프로미스 작업 방식이 도입되었다.

프로미스 다시 보기


새로운 문법을 살펴보기 전에 프로미스를 사용하는 일반적인 방싱을 간단히 리뷰해보자.

// 깃허브 사용자 정보 조회
fetch("https://api.github.com/users/AlbertMontalesi")
  .then((res) => {
    // 응답을 json형식으로 반환
    return res.json();
  })
  .the((res) => {
    // 성공 시 데이터를 출력
    console.log(res);
  })
  .catch((err) => {
    // 실패 시 오류 출력
    console.log(err);
  });

이것은 깃허브 API로 특정 깃허브 사용자에 대한 정보를 가져와서 콘솔에 출력하는 매우 간단한 프로미스 코드다.

또 다른 예를 살펴보자.

function walk(amount) {
  return new Promise((resolve, reject) => {
    if (amount < 500) {
      reject("the value");
    }
    setTimeout(() => resolve(`you walked for ${amount} milliseconds`), amount);
  });
}

walk(1000)
  .then((res) => {
    console.log(res);
    return walk(500);
  })
  .then((res) => {
    console.log(res);
    return walk(700);
  })
  .then((res) => {
    console.log(res);
    return walk(800);
  })
  .then((res) => {
    console.log(res);
    return walk(100);
  })
  .then((res) => {
    console.log(res);
    return walk(400);
  })
  .then((res) => {
    console.log(res);
    return walk(600);
  });

// you walked for 1000 milliseconds
// you walked for 500 milliseconds
// you walked for 700 milliseconds
// you walked for 800 milliseconds
// uncaught exception: the value is too small

단순한 흐름이므로 특별히 설명할 것은 없다. 이제 async/await 문법을 사용해서 이 예제의 프로미스를 어떻게 다시 작성할 수 있는지 살펴보자.

aync/await


다음 코드를 보자.

function walk(amount) {
  return new Promise((resolve, reject) => {
    if (amount < 500) {
      reject("the value");
    }
    setTimeout(() => resolve(`you walked for ${amount} milliseconds`), amount);
  });
}

async function go() {
  // 프로미스가 완료될 때까지 기다리기 위해 await 키워드를 사용
  const res = await walk(500);
  console.log(res);
  const res2 = await walk(900);
  console.log(res2);
  const res3 = await walk(600);
  console.log(res3);
  const res4 = await walk(700);
  console.log(res4);
  const res5 = await walk(400);
  console.log(res5);
  console.log("finished");
}

// you walked for 500 milliseconds
// you walked for 900 milliseconds
// you walked for 600 milliseconds
// you walked for 700 milliseconds
// uncaught exception: the value is too small

이 예제 코드를 하나씩 분석해보자.

  • 비동기 함수를 만들려면 함수 앞에 async 키워드를 넣어야한다.
  • 해당 키워드는 자바스크립트에게 항상 프로미스를 반환하도록 지시한다.
  • 비동기 함수 내에서 프로미스가 아닌 값을 반환하게 작성하면 자바스크립트가 해당 값을 자동으로 프로미스로 감싼 후에 반환한다.
  • await 키워드는 비동기 함수 내에서만 작동한다.
  • 이름에서 알 수 있듯이 await 키워드는 프로미스가 결과를 반환할 때까지 기다리도록 자바스크립트에 지시한다.

비동기 함수가 아닌 곳에서 await 을 사용하려고 하면 어떤 일이 발생하는지 살펴보자.

// 일반 함수에서 await을 사용한 경우
function func() {
    let promise = Promise.resolve();
    let result = await promise;
}
func();
// SyntaxError: await is only valid in async functions and async generators

// 코드 최상위 레벨에서 await을 사용한 경우
let response = Promise.resolve();
let result = await response;
// SyntaxError: await is only valid in async functions and async generators

명심하자. await 는 비동기 함수 내에서만 사용할 수 있다

오류 처리


일반적인 프로미스에서는 .catch() 를 사용하여 프로미스가 반환하는 오류들을 처리한다. async/await 문법을 사용할 때도 크게 다르지 않다.

async function asyncFunc() {
  try {
    let response = await fetch("your-url");
  } catch (err) {
    console.log(err);
  }
}

asyncFunc();
// TypeError: failed to fetch

보통은 try ...catch 구문을 사용하여 오류를 처리하지만, 해당 구문 없이도 다음과 같이 오류를 처리할 수 있다.

async function asyncFunc() {
  let response = await fetch("your-url");
}

asyncFunc();
// Uncaught (in promise) TypeError: Faild to fetch

asyncFunc().catch(console.log);
// TypeError: failed to fetch
profile
클린 코드, 클린 아키텍처

0개의 댓글