Amada Coding Club

[Promise] Promise API에 대해 알아보자 본문

Front-End/관련 지식들

[Promise] Promise API에 대해 알아보자

아마다회장 2023. 2. 13. 11:45
 

[비동기] 비동기 함수에 대해 알아보자

최근에 Async와 await함수를 다루다가 Promise는 무엇이고 비동기 함수, 그리고 callback은 무엇인지 궁금해졌다. 이를 정리해보려고 한다. 프론트엔드에서도 데이터 처리는 많이 일어나기 때문에 비동

amadaclub.tistory.com

지난 게시글에서 비동기 함수에 대해서 알아보았다.

어떠한 비동기 함수가 종료되고 나서 처리되는 함수로 콜백함수를 사용한다고 했다.

그러나 콜백함수는 콜백이 연달아 호출되며 가독성을 떨어트리는 콜백 지옥을 일으킬 수 있다. 

이 문제를 해결하기 위해 콜백함수를 분리하는 방법을 사용할 수 있지만 다른 방법으로 Promise(프로미스 or 프라미스)를 사용할 수도 있다. 

 

Promise

 

비동기 처리를 하고자 할 때 Promise를 반환하고, 비동기 함수는 Promise 객체 안에서 처리된다.

이때 프로미스는 다음 세 가지 상태를 가진다.

 

1. pending(대기) 완료되지도 거부되지도 않은 초기 상태

2. fulfilled(이행 === 완료) 비동기 처리가 성공적으로 마친 상태

3. rejected(거부) 비동기 처리가 비정상적으로 종료된 상태

 

프로미스는 이행 상태와 거부 상태일 때 처리하는 콜백함수인 resolve와 reject를 인자로 가진다. 

let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout( function() {
    resolve("성공!")
  }, 250)
})

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

위 코드는 공식 문서에서 가지고 온 코드다. setTimeout을 사용해 비동기 처리 예시를 보여줬다. 

setTimeout이 정상적으로 실행된다면 resolve함수가 실행되도록 설정한다.(resolve함수가 어떻게 사용되는지는 아래에 있다. )

위 코드에선 없지만 정상적으로 실행되지 않는다면 reject함수를 통해 사용할 수 있다. 

만약 매개변수가 필요한 비동기 함수라면 아래와 같이 입력하면 된다.

const promiseAjax = (method, url, payload) => {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open(method, url); 
    xhr.setRequestHeader('Content-type', 'application/json'); //비동기처리
    xhr.send(JSON.stringify(payload));

    xhr.onreadystatechange = function () { //비동기 처리가 끝나고 실행되는 함수
      // 서버 응답 완료가 아니면 무시
      if (xhr.readyState !== XMLHttpRequest.DONE) return;

      if (xhr.status >= 200 && xhr.status < 400) {
        // resolve 메소드를 호출하면서 처리 결과를 전달
        resolve(xhr.response); // Success!
      } else {
        // reject 메소드를 호출하면서 에러 메시지를 전달
        reject(new Error(xhr.status)); // Failed...
      }
    };
  });
};

https://poiemaweb.com/es6-promise 에서 가지고 왔다. ajax통신을 보여주고 있다.

이때 중요하게 볼 점은 생성된 Promise 객체를 반환한다는 점이다. 

그리고 Promise 안에서 비동기 처리가 일어나고 처리 결과에 따라 resolve와 reject가 호출된다,

 

자 이제 이 resolve와 reject는 어떻게 사용될까?

결론부터 말하면 resolve는 then(), reject는 catch()를 통해 사용된다.

 

후속처리함수

우선 then에 대해 알아보자. 

then은 두 개의 콜백함수를 인자 가진다. 첫 번째는 resolve가 호출 될 때, 두 번째는 reject가 호출될 때 실행된다.

비동기함수.then(resolve 될 때, reject될 때)

각 콜백함수는 파라미터로 resolve나 reject를 실행할 때 보냈던 인자들을 받는다. 

그리고 다시 Promise를 반환한다.

 

catch의 경우 reject될 때만 실행되고 하나의 인자를 가진다. 

catch도 마찬가지로 파라미터로 reject를 실행할 때 보냈던 인자들을 사용한다.

 

then은 두번째 인자로 reject가 실행될 때(에러 코드) 실행된다고 했다. 

그러나 이것보다 catch를 사용하는 것이 더 바람직하다

프라미스.then(() => {
	console.log("성공")
    throw new Error("실패")
}, 
 (e) => {console.log("실패")}
)

프라미스가 성공하고 실행되는 then에서 에러가 발생할 때, 같은 then에 위치한 reject처리 콜백은 이 오류를 감지하지 못한다. 첫 번째 then에서 발생한 오류를 감지하기 위해선 아래와 같이 입력해야 한다.

프라미스.then(() => {
	console.log("성공")
    throw new Error("실패")
}, 
 (e) => {console.log("실패")}
).then(undefined, (e) => console.log("에러"))

이 then(undefined, e=> 에러처리 함수)의 역할을 해주는 놈이 catch이다.

catch를 사용하게 되면 then(undefined, e=> 에러처리 함수)같이 사용돼 코드 가독성을 훨씬 높일 수 있다. 

 

 

아직 솔직히 프로미스에 대해 완전히 이해했다고는 말 못하겠다.

그래도 꾸준히 공부하면 어느 정도 성과를 보일 수 있지 않을까 생각한다. 

다음엔 이 글을 작성하게 만든 async와 await에 대해 알아보자.

 

참조

https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

https://poiemaweb.com/es6-promise

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