[JS] Promise

이재훈·2023년 6월 5일
0

javascript

목록 보기
10/13

Promise

자바스크립트의 비동기를 돕는 객체입니다. Promise 객체를 이용하면 콜백 지옥을 방지할 수 있습니다.

비동기 작업이 가질 수 있는 3가지 상태

  • Pending(대기 상태) : 비동기 작업이 진행중이거나 비동기 작업이 시작할 수도 없는 문제가 발생했음을 의미
  • Fulfilled(성공) : 이행 또는 성공 상태로 비동기 작업이 의도한대로 정상 수행했음을 의미
  • Rejected(실패) : 거부 또는 실패를 의미 ex) 서버 응답 x, timeout 등
function checkPositive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number !== "number") {
      reject("주어진 값이 숫자형 값이 아님");
    } else {
      resolve(number > 0 ? "양수" : "음수");
    }
  }, 2000);
}

checkPositive(
  20,
  (res) => {
    console.log(`성공 : ${res}`);
  },
  (err) => {
    console.log(`실패 : ${err}`);
  }
);

위 코드는 매개변수로 전달받은 number가 양수인지 음수인지 확인하는 함수입니다. 잘못된 자료형을 보내면 reject 콜백 함수를 호출하고 맞는 number 형이 들어왔을 시 양수인지 음수인지 출력합니다.

이제 이 코드를 promise를 사용하여 바꾸어보도록 하겠습니다.

function checkPositiveP(number) {
  const executor = (resolve, reject) => {
    setTimeout(() => {
      if (typeof number !== "number") {
        reject("주어진 값이 숫자형 값이 아님");
      } else {
        resolve(number > 0 ? "양수" : "음수");
      }
    }, 2000);
  };
  const asyncWork = new Promise(executor);
  return asyncWork;
}
const result = checkPositiveP(10);

result
  .then((res) => {
    console.log(`작업 성공 : ${res}`);
  })
  .catch((err) => {
    console.log(`작업 실패 : ${err}`);
  });

해당 코드에서 눈 여겨볼 점은 executor 함수를 Promise 객체의 매개 변수로 담아 리턴합니다. 여기서 asyncWork의 자료형은 Promsie<any> 입니다.

promise 객체의 메서드인 then과 catch를 사용하여 resolve 함수는 then 콜백함수를, reject 함수는 catch 콜백함수를 실행하게 됩니다.

이제 전에 콜백 콜백 콜백 구조를 Promise 객체를 사용하여 바꿔보도록 하겠습니다.

기존 코드

function work1(a, b, cb) {
  setTimeout(() => {
    const result = a + b;
    cb(result);
  }, 3000);
}

function work2(a, cb) {
  setTimeout(() => {
    const result = a * 2;
    cb(result);
  }, 1000);
}

function work3(a, cb) {
  setTimeout(() => {
    const result = a * -1;
    cb(result);
  }, 2000);
}

work1(3, 4, (result1) => {
  console.log(`work1 result = ${result1}`);
  work2(result1, (result2) => {
    console.log(`work2 result = ${result2}`);
    work3(result2, (result3) => {
      console.log(`work3 result = ${result3}`);
    });
  });
});

Promise 사용

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

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

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

work1(2, 3).then((result1) => {
  console.log(`result1 : ${result1}`);
  work2(result1).then((result2) => {
    console.log(`result2 : ${result2}`);
    work3(result2).then((result3) => {
      console.log(`result3 : ${result3}`);
    });
  });
});

work1,2,3에 각각 Promise 객체를 사용하여 동일한 결과를 얻었습니다. 하지만 해당 코드는 콜백지옥과 별반 다를 바가 없습니다.

then 체이닝 사용

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

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

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

work1(2, 3)
  .then((result1) => {
    console.log(`result1 : ${result1}`);
    return work2(result1);
  })
  .then((result2) => {
    console.log(`result2 : ${result2}`);
    return work3(result2);
  })
  .then((result3) => {
    console.log(`result3 : ${result3}`);
  });

호출부를 변경하였습니다. then체이닝을 사용하여 콜백지옥을 없앴습니다. 훨씬 가독성이 좋아진 것을 확인 수 있고, 유지보수도 더 쉬워졌습니다.


해당 게시글은 인프런 강의
"한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지(이정환)"
를 정리한 내용입니다. 쉽게 잘 설명해주시니 여러분도 강의를 듣는 것을 추천드립니다.

profile
부족함을 인정하고 노력하자

0개의 댓글