관리 메뉴

너와 나의 스토리

Javascript 비동기 처리 - Promise, async/await 사용법 정리 본문

개발/Front-End

Javascript 비동기 처리 - Promise, async/await 사용법 정리

노는게제일좋아! 2023. 11. 11. 15:54
반응형

* 아래 내용은 '벨로퍼트와 함께하는 모던 자바스크립트' 튜토리얼을 따라 요약 또는 내용 추가한 것으로 자세한 내용은 해당 강의를 참고해 주시기 바랍니다.

 

Promise

  • 비동기 작업을 조금 더 편하게 처리 할 수 있도록 ES6에 도입된 기능
  • 예제: 숫자 n을 파라미터로 받아와서 다섯 번에 걸쳐 1초마다 1씩 더해서 출력하는 작업을 setTimeout으로 구현
function increaseAndPrint(n, callback) {
  setTimeout(() => {
    const increased = n + 1;
    console.log(increased);
    if (callback) {
      callback(increased);
    }
  }, 1000);
}

increaseAndPrint(0, n => {
  increaseAndPrint(n, n => {
    increaseAndPrint(n, n => {
      increaseAndPrint(n, n => {
        increaseAndPrint(n, n => {
          console.log('끝!');
        });
      });
    });
  });
});
  • 이러한 콜백 중첩은 복잡성을 증가시킬 수 있으며, 이를 "콜백 지옥(callback hell)"이라고 부른다. 
  • JavaScript에서는 이 문제를 해결하기 위해 Promise나 async/await와 같은 개념을 도입하여 더 깔끔하고 관리하기 쉬운 코드를 작성할 수 있다.

 

Promise 만들기

const myPromise = new Promise((resolve, reject) => {
  // 구현..
})
  • Promise가 성공 할 때는 resolve를 호출하고, 실패할 때는 reject를 호출하면 된다. 
  • 예제 1: 성공/또는 실패하는 코드 작성
const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1);
    //   reject(new Error());
    }, 1000);
  });
  
  myPromise
    .then(n => {  // resolve가 호출되면 여기로 들어옴
      console.log(n);
    })
    .catch(error => {  // reject가 호출되면 여기로 들어옴 
      console.log(error);
    });
  • 예제 2: 1부터 4까지 숫자 출력, value가 5 이상이면 reject 호출하고 바로 끝!
    • 5번째로 increaseAndPrint() 메서드가 호출될 때, reject가 호출된다. 그러면 그 이후, 6번째 increaseAndPrint는 호출되지 않는다.
function increaseAndPrint(n) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        const value = n + 1;
        if (value === 5) {
          const error = new Error();
          error.name = 'ValueIsFiveError';
          reject(error);
          return;
        }
        console.log(value);
        resolve(value);
      }, 1000);
    });
  }
  
  increaseAndPrint(0)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .then(increaseAndPrint)
    .catch(e => {
      console.error(e);
    });

 

 

async/await

  • async/await 문법은 ES8에 해당하는 문법으로, Promise를 더욱 쉽게 사용할 수 있게 해 준다.
  • 예제 1:
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 키워드를 붙이고, Promise의 앞부분에 await를 넣어주면 해당 프로미스가 끝날 때까지 기다렸다가 다음 작업을 수행할 수 있다.
  • 예제 2: 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();
  • Promise.all을 사용할 때는, 등록한 promise 중에 하나라도 실패하면, 모든 게 실패한 것으로 간주한다.
  • 예제 3: Promise.race를 사용하여 가장 빨리 끝나는 promise에 대한 결괏값만 가져오기.
async function process() {
  const first = await Promise.race([
    getDog(),
    getRabbit(),
    getTurtle()
  ]);
  console.log(first);
}

process();
반응형
Comments