Promise?

Promise란 JavaScript에서 제공하는 객체로, 비동기 처리를 위해 사용한다. Promise를 통해 수행한 작업이 성공한다면 성공 메시지와 결과값을 전달해주고, 에러가 날 경우 해당 에러를 전달해준다. 위에서 수행하는 작업은 비동기 작업으로 보통 서버에서 데이터를 가져오거나 하는 서버와의 통신을 말한다.

 

이전에는 비동기 작업을 여러 개의 Callback함수를 통해 처리를 했는데, 이럴 경우 아래와 같이 코드가 지저분해지고 가독성이 떨어진다. 이때 Promise를 사용한다면 이러한 콜백 지옥에서 벗어난 훨씬 더 간단하고 가독성 좋은 코드를 작성할 수 있다.

 

callback hell

 

상태

Promise는 다음과 같이 3가지의 상태를 가진다.

  • pending: Promise를 만들고, 작업이 수행중이거나 아직 완료되지 않은 상태
  • fulfilled: 작업이 성공적으로 수행되어 결과 값을 반환한 상태
  • rejected: 작업이 실패하여 에러가 발생한 상태

 

Promise 생성

먼저 Promise객체를 만들어보자. 다음과 같이 Promisenew연산자를 통해 만들 수 있다. 또한 Promiseexecutor콜백함수를 받는데, 비동기 작업을 성공했을 때의 콜백함수인 resolve와 실패했을 때의 콜백함수인 reject가 그것이다. 즉 Promise는 성공적으로 수행할 경우 resolve를 호출하고 실패할 경우 reject를 호출한다. 이러한 resolverejectPromise가 만들어지는 순간 자동적으로 실행이 되기 때문에 주의해야한다. 

 

const promise = new Promise((resolve, reject) => {
  // 비동기 처리를 위한 코드
});

 

출처: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

 

resolve

Promise의 결과 값은 resolve reject콜백함수를 통해 받아올 수 있다. resolve는 성공적으로 수행되었을 때, Promise상태 중 fulfilled상태이다. 아래와 같이 promise변수에 Promise를 만들어 담는데, 서버와 통신을 하는 것처럼 setTimeout으로 1초 뒤 resolve콜백함수에 'Hello!'를 전달하여 호출한다. 

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Hello!');
  }, 1000);
});

 

 

그리고 위에서 만든 Promise를 사용해보자. Promisethen, catch, finally를 통해 간단하게 사용할 수 있다.

 

promise.then((value) => {
  console.log(value);    // Hello!
});

 

then은 정상적으로 잘 수행이 되었을 경우에 자신이 원하는 작업을 할 때 사용한다. 즉 resolve콜백함수로 넘겨준 값들을 사용할 수 있다. 그리고 resolve에 넘겨준 값인 'Hello!'는 value에 할당이 된다. 

 

reject

reject는 비동기 작업이 어떠한 이유로 실패했을 때의 상태를 나타낸다. 아래와 같이 reject는 보통 Error객체를 생성하여 에러의 내용을 담아 호출한다. 

 

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('Something went wrong!'));
  }, 1000);
});

 

then을 통해 성공적으로 수행된 경우인 resolve를 다뤘다면, catch를 통해 비동기 작업이 실패했을 때의 reject와 에러를 다룰 수 있다.

 

promise
  .then((value) => {
    console.log(value); // Hello!
  })
  .catch((error) => {
    console.log(error); // Something went wrong!
  });

 

위와 같이 catch를 사용하면 reject에 넘겨준 에러 메시지인 Something went wrong!이 error에 할당이 되는 것을 볼 수 있다.

 

그렇다면 finally는 어떨 때 사용하는 것일까? 이 finally는 비동기 처리의 성공과 실패에 상관없이 무조건적으로 실행할 코드를 작성한다. 

 

promise
  .then((value) => {
    console.log(value); 
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("finally");
  });

 

Promise Chaining

then사용하면 또 다른 새로운 Promise객체를 반환하기 때문에, Promise들을 여러개 연결을 할 수 있다. 예시를 통해 살펴보자. 1초 뒤에 숫자 1을 전달하는 Promise가 있다고 하자. 그리고 이 숫자가 성공적으로 전달이 되면 Promise들을 연결하여 그 숫자에 10을 더하고, 그 다음에는 100을 더하고 마지막에는 1000을 더하게 할 수 있다.

 

const promiseChaining = new Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000);
});

promiseChaining
  .then((num) => {
    console.log(num);  // 1
    return num + 10;
  })
  .then((num) => {
    console.log(num);  // 11
    return num + 100;
  })
  .then((num) => {
    console.log(num);  // 111
    return num + 1000;
  });

 

위처럼 then에는 num과 같이 값을 전달할 수 있고, 아래와 같이 또 다른 Promise를 전달할 수도 있다.

 

promiseChaining
  .then((num) => {
    console.log(num);  // 1
    return num + 10;
  })
  .then((num) => {
    console.log(num);  // 11
    return num + 100;
  })
  .then((num) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(num - 10), 1000);
    });
   })
   .then(num => console.log(num));  // 101

 

 

이처럼 JavaScript에서 비동기적 처리를 할 때 콜백 함수를 이용하여 처리를 하지말고 Promise객체를 사용하면 깔끔하고 가독성 좋게 코드를 작성할 수 있다. 다음으로는 비동기 처리에 사용되는 문법 중 가장 최근에 나온 문법인 asyncawait를 포스팅할 예정이다 🐙

 

 

 

참고


생강강

,