[JS] Promise를 사용한 비동기 처리

손규성·2022년 10월 30일
1

javascript

목록 보기
5/8
post-thumbnail

Promise 자세히


  • Promise는 자바스크립트에서 비동기 처리에 사용되는 객체이다.
  • 특정 시점에서 특정 코드를 수행시킬 수 있도록 해주며, callback 함수를 사용해서 동 기능을 구현했을 때 발생하는 콜백지옥을 방지할 수 있도록 구현되어 있다.
  • 정해진 기능이 정상적으로 수행되었을 때 결과 값을 전달하고, 예외가 발생하면 에러를 전달한다.
  • Promise는 resolve와 reject를 인자로 하는 함수를 인자로 받으며 Promise((res, rej) => {}) resolve와 reject 중 하나는 무조건 실행된다.
  • Promise는 주로 네트워크/파일에서 데이터를 받아올 때 사용된다. (데이터를 받아오는 작업은 시간이 오래 걸리는 경우가 많은데, 이 부분을 동기적으로 처리하게 되면 다른 작업을 수행할 수 없기 때문)

💡Promise의 3가지 상태

  1. Pending(대기): 비동기 처리 로직이 아직 완료되지 않은 상태
  2. Fulfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
  3. Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태


Promise 생성/사용


  • Promise는 class 객체이기 때문에 아래와 같이 생성한다.
  • 이때 유의해야 할 점은 Promise를 생성만 하고 아직 호출하지 않아도 'Here is a promise'가 콘솔에 찍힌다는 점이다. 즉, Promise는 생성됨과 동시에 executor 함수를 실행함으로서 불필요한 작업이 실행되지 않도록 유의해야 한다.
const promise = new Promise((resolve, reject) => {
	console.log('Here is a promise');
});

//Output: 'Here is a promise'
  • 데이터를 받아올 때 사용되는 시간을 임의적으로 구현하기 위해 setTimeout을 사용하면 아래와 같이 코드를 수정할 수 있다.
const promise = new Promise((resolve, reject) => {
	console.log('Here is a promise');
  	setTimeout(() => {
      resolve('James');
    }, 2000);
});

// 2초 동안 어떠한 작업을 진행한 후 resolve 콜백함수를 통해 `James`라는 값을 반환하는 Promise producer 
  • Promise를 사용하기 위해서는 Promise를 사용하는 consumer를 작성해야 한다.
  • consumer는 then, catch, finally를 사용해서 Promise를 사용할 수 있다.
const promise = new Promise((resolve, reject) => {
	console.log('Here is a promise');
  	setTimeout(() => {
      resolve('James');
    }, 2000);
});

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

//Output: James
  • then은 resolve를 통해 반환되는 값이 인자로 받는 함수이다.
  • 해당 예시에서는 James라는 값이 전달되고, then의 인자를 찍으면 James가 출력된다.
const promise = new Promise((resolve, reject) => {
	console.log('Here is a promise');
  	setTimeout(() => {
      //resolve('James');
      reject(new Error('No User Info Available'));
    }, 2000);
});

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

//Output: Error: No User Info Available 
  • catch는 반대로 executor 함수가 정상적으로 작동하지 않았을 경우를 다룬다.
  • 기존 코드에서 resolve 부분은 주석처리 해주고, reject를 통해 No User Info Available이라는 Error를 반환하게 한다.
  • 이후 then 뒤에 catch를 체이닝해서 reject를 통해 반환되는 값을 찍어보면 콘솔창에 에러가 뜬다.
  • 이때 then뒤에 바로 catch를 체이닝할 수 있는 이유는 then도 결국 똑같은 Promise를 반환하기 때문이다. 이 체이닝이 이해가 안된다면 아래 예시를 참고하면 된다.
let str = 'ayaye';
let replaced = str
	.replaceAll('aya', 1)
	.replaceAll('ye', 2); 

console.log(replaced); 

//output: 12
  • str에 replaceAll을 한번 사용하면 1ye 를 반환하고, 그 값에 다시 replaceAll을 사용하면 12가 반환되게 되는 것이다. 이처럼 반환값에 맞춰 여러 메서드를 체이닝해서 사용할 수 있는 것과 같은 로직이라고 보면 된다.
  • 마지막으로 finally는 코드의 성공/실패 여부와 상관없이 무조건 진행되는 내용이다.
const promise = new Promise((resolve, reject) => {
	console.log('Here is a promise');
  	setTimeout(() => {
      resolve('James');
      //reject(new Error('No User Info Available'));
    }, 2000);
});

promise
  .then(value => {
  	console.log(value);
})
  .catch(error => {
  	console.log(error);
})
  .finally(() => {
  	console.log('promise is over!');
});

/*
Output: 
James
promise is over!
*/

💡Example:

const getPig = () => 
    new Promise((res, rej) => {
      setTimeout(() => res('🐷'), 1000);
    })
  const getFire = pig => 
    new Promise((res, rej) => {
      setTimeout(() => res(`${pig} + 🔥`), 1000);
    })
  const getBacon = fire => 
    new Promise((res, rej) => {
      setTimeout(() => res(`${fire} = 🥓`), 1000);
    })


getPig()
    .then(getFire)
    .then(getBacon)
    .then(console.log)

//Output: 🐷 + 🔥 = 🥓

Example Reference: 드림코딩: 자바스크립트 12. 프로미스 개념부터 활용까지 JavaScript Promise | 프론트엔드 개발자 입문편 (JavaScript ES6)



마무리


  • 처음에 Promise에 대해 배우면서 정말 낯설게 다가왔다. 근데 구글센세를 통해 여러 유용한 자료를 찾아보고, 실제 사용 예시를 보면서 많이 익숙해진 것 같다.
  • 무엇보다 어떤 상황에서, 왜 사용되어야 하는지에 대해 찾아보는 게 많이 도움이 되었다.
  • 실습해보면서 더 다양하게 방법으로 사용해보고 싶다.
  • Promise가 아직 잘 이해되지 않는다면 링크되어 있는 드림코딩님의 영상을 시청하는 것을 추천한다!

References

  1. 드림코딩: 자바스크립트 12. 프로미스 개념부터 활용까지 JavaScript Promise | 프론트엔드 개발자 입문편 (JavaScript ES6)
  2. MDN: Javascript Promise
  3. 캡틴 판교: 자바스크립트 Promise 쉽게 이해하기
profile
블로그 이사 → https://sqsung.tistory.com/

0개의 댓글