SUE 개발 블로그

자바스크립트 Promise 콜백 지옥 탈출 본문

JavaScript

자바스크립트 Promise 콜백 지옥 탈출

이수광 2023. 12. 18. 03:04

ㅈ..지옥

콜백 지옥은 위와 같이 연속되는 비동기 함수들을 처리할 때 비동기 함수들의 결과 값을

사용하기 위해서 콜백이 계속 깊어지는 현상을 뜻한다.

 

이 콜백 함수를 해결할 수 있는 자바스크립트의 Promise 객체에 대해 알아보자.

 

자바스크립트의 비동기를 돕는 객체. 

Promise 객체를 이용하면 비동기 처리의 결과 값을 핸들링하는 코드를 비동기 함수로 부터 분리할 수 있다.

더 이상 비동기 처리 함수에 콜백을 줄지어 전달할 필요가 없어 쉽고 빠르고

직관적으로 비동기 처리를 만들 수 있다.

 

비동기로 동작하는 작업이 가질 수 있는 상태에 대해 미리 알아보자.

 

Pending ( 대기상태 )  대기상태로 현재 비동기 작업이 진행 중이거나 작업이 시작되지 않는 문제 발생 의미

Fulfilled   ( 성공 )  이행 또는 성공 상태로 비동기 작업이 우리가 의도한 대로 정상적 완료된 상태 의미

Rejected ( 실패 )  거부 또는 실패 상태로 비동기 작업이 모종의 이유로 실패했음을 의미

( 서버응답 X 장시간 작업으로 자동취소 )

 

* 비동기 작업은 한 번 성공하거나 실패하면 그걸로 작업이 끝난다. * 

 

비동기 작업에서 Pending 상태에서 성공 상태인 Fulfilled 로 변화하는 과정을 resolve 로 부르고

반대로 Pending 상태에서 실패 상태인 Rejected 거부라는 의미로 reject 라고 부를 수 있다.


실행시 2초 뒤 입력한 값이 양수인지 음수인지 판별하는 프로그램을 짜보자.

function isPostive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number === "number") {
      // 성공 -> resolve
      resolve(number >= 0 ? "양수" : "음수");
    } else {
      // 실패 -> reject
      reject("주어진 값이 숫자형 값이 아닙니다.");
    }
  }, 2000);
}

isPostive(
  20,
  (res) => {
    console.log("성공적 수행됨 : ", res);
  },
  (err) => {
    console.log("실패 하였음 : ", err);
  }
);

위의 프로그램은 Promise 객체를 이용해 처리해보자.

function isPostiveP(number) {
  const exector = (resolve, reject) => {
    // exector = 실행자
    setTimeout(() => {
      if (typeof number === "number") {
        // 성공 -> resolve
        console.log(number);
        resolve(number >= 0 ? "양수" : "음수");
      } else {
        // 실패 -> reject
        reject("주어진 값이 숫자형 값이 아닙니다.");
      }
    }, 2000);
  };
  const asyncTask = new Promise(exector);
  return asyncTask;
}

const res = isPostiveP(232);
res
  .then((res) => {
    console.log("작업 성공 : ", res);
  })
  .catch((err) => {
    console.log("작업 실패 : ", err);
  });

이제 배운 Promise 를 이용하여 위에서 언급했던 콜백 지옥을 어떻게 탈출하는지 지켜보자.

 

점점 콜백이 깊어지면서 옆으로 밀려나가는 코드들을 볼 수 있다.

Promise 를 사용했음에도 똑같이 콜백 지옥이 펼쳐진 것을 볼 수 있다. 

분명 콜백 지옥을 벗어날 수 있다고 했는데 왜 이럴까?

Promise 객체와 메서드인 then을 콜백 함수를 쓰는 식으로 사용해서 그렇다.

제대로 바꿔서 사용해보자.

function taskA(a, b) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a + b;
      resolve(res);
    }, 3000);
  });
}

function taskB(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a * 2;
      resolve(res);
    }, 1000);
  });
}

function taskC(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = a * -1;
      resolve(res);
    }, 2000);
  });
}

taskA(5, 1)
  .then((a_res) => {
    console.log("A Result : ", a_res);
    return taskB(a_res);
  })
  .then((b_res) => {
    console.log("B Result : ", b_res);
    return taskC(b_res);
  })
  .then((c_res) => {
    console.log("C Result : ", c_res);
  });

이렇게 .then 메서드를 계속 이어서 붙이는 것을 then 체이닝이라고 부른다.

taskA() 의 결과 값인 a_res 를 인자로 전달한 taskB() 에 또 then 메서드를 이용하고 

그 결과 값인 b_res 를 taskC() 에 인자로 전달하고

taskC()에 또 then 메서드를 붙여서 호출하는 방식으로 사용한다.

 

이런 방식으로 사용하면 콜백식은 비동기 처리의 결과를 비동기 처리의 결과로 사용하려면

위와 같이 코드가 안으로 들어 가게되는데 Promise 를 이용하면 위와 같이 코드를

계속 아래로 늘여쓸 수 있다. 보기에도 직관적이고 다른 작업을 사이에 껴놓을 수도 있다.

 

 

'JavaScript' 카테고리의 다른 글

자바스크립트 API 호출하기  (2) 2023.12.26
자바스크립트 async & await  (0) 2023.12.19
자바스크립트 동기 & 비동기  (2) 2023.12.18
자바스크립트 This 란?  (0) 2023.12.12
자바스크립트 spread 연산자  (0) 2023.12.12