(JS) 벨로퍼트의 모던 자바스크립트 : async / await

호두파파·2021년 3월 2일
0

async / await 문법은 ES8에 해당하는 문법으로서, Promise를 더욱 쉽게 사용할 수 있게 해준다.

기본적인 문법

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

async function process() {
  console.log('안녕하세요!');
  await sleep(1000); // 1초 쉬고 
  console.log('반갑습니다!');
}

process();

async/await 문법을 사용할 때에는, 함수를 선언할때 함수의 앞 부분에 async키워드를 붙여준다. 그리고 Promise 앞부분에 await를 넣어주면 해당 프로미스가 끝날 때까지 기다렸다가 다음 작업을 수행할 수 있다.

위 코드에서는 sleep이라는 함수를 만들어서 파라미터로 넣어준 시간만큼 기다리는 Promise를 만들고, 이를 process함수에서 사용해주었다.

함수에서 async를 사용하면, 해당 함수는 결과값으로 Promise를 반환하게 된다.
따라서 다음과 같이 코드를 작성할 수 있다.

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

async function process() {
  console.log('안녕하세요!');
  await sleep(1000); // 1초 쉬고 
  console.log('반갑습니다!');
}

process().then(() => {
  console.log('작업이 끝났어요!');
});

async 함수에서 에러를 발생 시킬 때에는 throw를 사용하고, 에러를 잡아낼 때에는 try/catch 문을 사용한다.

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

async function makeError() {
  await sleep(1000);
  const error = new Error();
  throw error
}

async function process() {
  try {
    await makeError();
  } catch (e) {
    console.error(e);
  }
}

process();

Promise.all

서로 다르게 호출시간이 지정된 콜백함수를 동시에 작업 시작하고 싶다면, 다음과 같이 Promise.all을 사용해야 한다.

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

const getDog = async () => {
  await sleep(1000);
  return '멍멍이';
};

const getRabbit = async () => {
  await sleep(500);
  return '토끼';
};

const getTurtle = async () => {
  await sleep(3000);
  return '거북이';
};

async function process() {
  const results = await Promise.all([getDog(), getRabbit(), getTurtle()])
  console.log(results);
}

process();

여기서 배열 비구조화 할당 문법을 사용하면 각 결과값을 따로 따로 추출해서 조회할 수 있다.

//async function process() {
//  const results = await Promise.all([getDog(), getRabbit(), getTurtle()])
//  console.log(results);
//}

//process();

async function process() {
  const [dog, rabbit, turtle] = await Promise.all([
    getDog(),
    getRabbit(),
    getTurtle()
  ]);
  console.log(dog);
  console.log(rabbit);
  console.log(turtle);
}

process();

Promise.all을 사용할 때에는, 등록한 프로미스 중 하나라도 실패하면 모든게 실패한 것으로 간주한다.

반면 Promise.race는 여러개의 프로미스를 등록해서 실행했을 때 가장 빨리 끝난 것 하나만의 결과값을 가져온다.

async function process() {
  const first = await Promise.race([
    getDog(),
    getRabbit(),
    getTurtle()
  ]);
  console.log(first);
}

process();

Promise.race의 경우엔 가장 다른 Promise가 먼저 성공하기 전에 가장 먼저 끝난 Promise가 실패하면 이를 실패로 간주한다. 따라서, 현재 위 코드에서 getRabbit에서 에러를 발생시킨다면 에러를 잡아낼 수 있지만, getTurtle이나 getDog에서 발생한 에러는 무시된다.

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글