Promise 이해하기

kim yeseul·2023년 10월 24일
0

Javascript

목록 보기
7/8
post-thumbnail
post-custom-banner

Promise란 무엇인가?

Promise는 자바스크립트 비동기 처리에 사용되는 객체로 비동기 작업의 완료 또는 실패와 그 결과 값을 나타낸다. 여기서 자바스크립트의 비동기 처리란 '특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성'을 의미한다.

Promise는 왜 필요할까?

Promise는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용한다. 일반적으로 웹 어플리케이션 구현 시 서버에서 데이터를 요청하고 받아오기 위해 위와 같은 API를 사용하게 된다.

$.get('url 주소/products/1', function(response) {
  // ...
});

여기서, 위 로직은 문제가 있다

➡️ 데이터를 받아오는 데에는 시간이 걸리는데 위 로직처럼 데이터를 불러오면 데이터가 다 받아와지지도 않았는데 화면에 데이터를 표시하려는 상황이 되어 오류가 발생하거나 빈 화면이 뜨게 된다. 이와 같은 문제를 해결하기 위한 방법 중 하나가 프로미스인 것이다.

코드로 알아보자.

function getFetchData(callback) {
  return new Promise(function(resolve, reject) {
    $.get('api/products/1', function(response) {
      // 데이터를 받으면 resolve() 호출
      resolve(response);
    });
  });
}

// getData()의 실행이 끝나면 호출되는 then()
getFetchData().then(function(data) {
  // resolve()의 결과 값이 여기로 전달됨
  console.log(data); // $.get()의 response 값이 data에 전달됨
});

new Promise(), resolve(), then()와 같은 프로미스 API를 사용한 모습이 보인다.

프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있다. 다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '약속'(프로미스)을 반환하는 것이다

프로미스의 3가지 상태

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

대기(Pending)

비동기 처리 로직이 아직 완료되지 않은 상태

➡️ new Promise() 메서드를 호출하면 대기(Pending) 상태가 된다.

new Promise();

➡️ new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있다. 인자는 resolve, reject

new Promise(function(resolve, reject) {
  // ...
});

이행(Fulfilled)

비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태

➡️ resolve()를 실행하면 이행(Fulfilled) 상태가 된다

new Promise(function(resolve, reject) {
  resolve();
});

➡️ 이행 상태가 되면 then()을 이용하여 처리 결과 값을 받을 수 있다.

function getFetchData() {
  return new Promise(function(resolve, reject) {
    let data = 100;
    resolve(data);
  });
}

// resolve()의 결과 값 data를 resolvedData로 받음
getFetchData().then(function(resolveData) {
  console.log(resolveData); // 100
});

거부(Rejected)

비동기 처리가 실패하거나 오류가 발생한 상태

➡️ reject()를 실행하면 거부(Rejected) 상태가 된다

new Promise(function(resolve, reject) {
  resolve();
});

➡️ 거부 상태가 되면 거부한 이유(실패 처리 결과 값)을 catch()로 받을 수 있다

function getFetchData() {
  return new Promise(function(resolve, reject) {
    reject(new Error('Request is failed!'));
  });
}

// reject()의 결과 값 Error를 err에 받음
getFetchData().then().catch(function(err) {
  console.log(err);
});

화살표 함수를 사용한 예제

출처: mdn

let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout(function () {
    resolve("성공!"); // 와! 문제 없음!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  console.log("와! " + successMessage);
});

resolve(), reject() 함께 사용하기

function getFetchData() {
  return new Promise((resolve, reject) => {
    $.get('api/products/1', (response) => {
      if (response) {
        resolve(response);
      } else {
        reject(new Error("Request is failed"));
      }
    });
  });
}

// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getFetchData().then((data) => {
  console.log(data); // response 값 출력
}).catch((err) => {
  console.error(err); // Error 출력
});

➡️ 위 코드는 서버에서 응답을 제대로 받아오면 resolve() 메서드를 호출하고, 응답이 없으면 reject() 메서드를 호출한다. 호출된 메서드에 따라 then()이나 catch()로 응답 결과 또는 오류를 출력한다.

Promise 에러 처리 방법

1. then()의 두 번째 인자로 에러를 처리

getFetchData().then(
  onSuccess,
  onError
);

// 코드 예시
getFetchData().then(() => {
  // ...
}, (err) => {
  console.log(err);
});

2. catch()를 이용

getFetchData().then().catch();

// 코드 예시
getFetchData().then().catch((err) => {
  console.log(err);
});

에러 처리는 가급적 catch()를 사용하는 것이 더 효율적이다!

➡️ then()의 두 번째 인자로 에러를 처리했을 때는 오류를 제대로 잡아내지 못하는 경우가 있기 때문!


profile
출발선 앞의 준비된 마음가짐, 떨림, 설렘을 가진 주니어 개발자
post-custom-banner

0개의 댓글