Promise란?

경규혁·2023년 5월 19일
0

Promise란?

Promise는 프로미스가 생성된 시점에는 알려지지 않았을 수도 있는 값을 위한 대리자로, 비동기 연산이 종료된 이후에 결과 값과 실패 사유를 처리하기 위한 처리기를 연결할 수 있습니다. 프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다. 다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '약속'(프로미스)을 반환합니다.

Promise MDN 공식문서

Promise를 다루기 전에 동기와 비동기란 무엇인가?

쉽게 말해 동기는 순서대로 실행, 비동기는 순서대로 실행되지 않는 것이라고 생각

JS의 경우에도 호이스팅 이후 순서대로 실행, 즉 동기적으로 작동한다.
코드를 위에서 부터 아래대로 순차적으로 읽어내는 것

console.log(1);
console.log(2);
console.log(3);
console.log(4);
// 코드가 실행되면 1,2,3,4가 동기적으로 실행될 것이다.

동기적으로 프로그램이 실행되면 생기는 문제점?

"동기적" 이라는 의미는 말 그대로 동시에 일어난다는 뜻으로, 요청하면 그 자리에서 결과가 바로 주어져야 한다. 결과가 오지 않으면 결과가 올때까지 기다리고 결과가 다 와야 다음 코드를 실행하게 된다.

예를 들어, A라는 작업이 10분, B라는 작업이 20분, C라는 작업이 30분, D라는 작업이 40분 걸린다면 코드를 실행 했을 때 A라는 작업이 10분 걸릴때까지 기다리고 결과가 오면, B라는 작업 20분, 다시 C라는 작업 30분, 마지막으로 D라는 작업 40분까지 결과가 끝날때까지 기다려야 한다.

JS 엔진은 기본적으로 싱글 쓰레드이기 때문에 2가지 일을 동시에 할 수 없고 1가지 일만 할 수 있다. 따라서 JS에서는 비동기적인 처리를 해서 동기적인 동작의 문제점을 개선할 수 있다.

Promise는 자바스크립트에서 비동기 처리에 사용되는 객체이다.

내용은 실행 되었지만 결과를 아직 반환하지 않은 객체라고 이해하면 편하다.
Promise는 뜻 그대로 '약속' 이라는 의미.
당장 데이터를 줄 수 없지만 제대로 처리가 되면 데이터를 넘겨주고 아니면 오류를 줄 것이라는 약속이다.

const promise = new Promise((resolve, reject) => {
  // 비동기 작업 수행 (네트워킹이나 파일 읽기와 같은무거운 작업)
});

일반적으로 Promise를 만드는 방법은 new Promise 키워드를 사용한다. Promise는 객체이기 때문에 new로 생성을 해주고 콜백 함수 2개를 받는 함수를 제공해준다.
비동기 작업이 제대로 수행이 되었다면, 콜백함수 resolve()를, 오류가 발생했다면 reject()를 호출한다.

Promise의 4가지 State

Pending (대기중): 프로미스 객체가 생성되었지만, 아직 결과가 이행(fulfilled)되거나 거부(rejected)되지 않은 상태. 비동기 작업이 진행 중인 동안 대기 중인 상태.

Fulfilled (이행됨): 프로미스가 성공적으로 결과를 반환하거나 해결된 상태. 즉, 프로미스가 작업을 성공적으로 완료한 상태를 의미한다. 프로미스가 이행되면 then() 메서드를 사용하여 결과를 처리할 수 있다.

Rejected (거부됨): 프로미스가 실패하거나 거부된 상태. 즉, 프로미스가 작업을 실패한 상태를 의미한다. 프로미스가 거부되면 catch() 메서드를 사용하여 에러를 처리할 수 있다.

Settled (결정됨): 프로미스가 이행(fulfilled)되거나 거부(rejected)된 상태를 가지는 것을 의미한다. 즉, 이행되거나 거부되었지만 더 이상 상태가 변하지 않는 상태이다. 프로미스가 결정되면 finally() 메서드를 사용하여 마무리 작업을 수행할 수 있다. finally() 메서드는 성공 또는 실패 여부와 관계없이 항상 호출된다.

자바스크립트 코드가 실행될 때 브라우저와의 동작하는 그림

구성요소

  1. Heap: 메모리 할당이 발생하는 곳
  2. Call Stack : 실행된 코드의 환경을 저장하는 자료구조, 함수 호출 시 Call Stack에 push 됩니다.
  3. Web APIs: DOM, AJAX, setTimeout 등 브라우저가 제공하는 API

참고자료

setTimeout(function ex() {
  console.log('second')
}, 1000);

위의 코드에서의 각 구성요소들이 하는 일은?

  1. Web APIs: setTimeout이 Call Stack에 들어와 실행되면 Browser API인 timer를 호출합니다.
  2. Event Table: 특정 event(timeout, click, mouse move 등등)가 발생했을 때 어떤 callback 함수가 호출되야 하는지를 알고 있는 자료구조입니다. 위 코드에서 호출된 timer가 종료되면 event가 발생하게 되는데 이때 ex callback 함수가 실행되어야 한다는 것을 Event Table이 알고 있습니다.
  3. Callback Queue: 이벤트 발생 시 실행해야 할 callback 함수가 Callback Queue에 추가됩니다.
  4. Event Loop: Event Loop의 역할은 간단합니다.
    (1) Call Stack과 Callback Queue를 감시합니다.
    (2) Call Stack이 비어있을 경우, Callback queue에서 함수를 꺼내 Call Stack에 추가합니다

Promise Chaining이란?

여러 개의 프로미스 연결하기를 의미한다.
프로미스의 또 다른 특징은 여러 개의 프로미스를 연결하여 사용할 수 있다는 점을 이용 -> then()메소드를 한번 호출하고 나면 새로운 프로미스 객체가 반환되는 특징을 이용하는 것이다.

// promise chaining 예시
const fetchNumber = new Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000);
});

fetchNumber
  .then((num) => num * 2)
  .then((num) => num * 3)
  .then((num) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(num - 1), 1000);
    });
  })
  .then((num) => console.log(num)); // 5가 출력된다.

promise의 error 처리 방식

catch()를 이용한 예외처리를 이용하는 것이 가장 일반적이다.

catch() 를 이용한 예외처리 예시
//Producer
function async_test() {
  return new Promise((resolve, reject) => {
    console.log("doing some things...");
    setTimeout(() => {
      reject(new Error("Error Message")); //일이 제대로 끝났으면 resolve 호출
    }, 2000);
  });
}
 
//Consumer
async_test() //
    .then((data) => console.log(data))
    .catch((error) => console.log(error)); // 예외 처리
profile
갓생살기 기원!

0개의 댓글