[JS] Promise - 콜백 지옥 탈출

n-u·2022년 6월 15일
0

TIL

목록 보기
8/24
post-thumbnail

콜백지옥

연속되는 비동기 함수를 처리할때, 비동기 처리의 결과 값을 사용하기 위해서
코드가 깊어지는 현상

Promise

자바스크립트의 비동기를 도와주는 객체
비동기 처리의 결과값을 핸들링 하는 코드를 비동기 함수로부터 분리할 수있다.
Promise객체를 사용하면 비동기 처리의 콜백함수를 줄지어 사용하지 않고 사용할 수 있어, 쉽고 빠르고 직관적으로 비동기 처리를 사용할 수 있다.

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

1. Pending(대기상태)

  • 현재 비동기 작업이 실행 중이거나, 시작할 수도 없는 문제가 발생했음을 나타냄

2. Fulfilled(성공)

  • 이행, 성공
  • 비동기 처리가 정상적으로 완료 되었음을 의미한다.

3. Rejected(실패)

  • 거부, 실패
  • 비동기 작업이 실행이 실패된 상태이며 서버가 응답이 없거나, 시간이 오래 걸릴때 자동으로 실행이 취소되는 상태

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

🔅 resolve와 reject

1. resolve 해결 : pending -> Fullfilled

비동기 작업을 했을때 그 작업이 성공했다! 즉, resolve가 이루어졌다.

2. reject 거부 : Pending -> Rejected

비동기 작업을 했을때 그 작업이 실패했다! 즉, reject가 이루어졌다.


콜백을 이용한 숫자값알아보는 함수

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

isPositive(
  [],
  (res) => {
    console.log("성공적으로 수행됨 :", res);
  },
  (err) => {
    console.log("실패 하였음 :", err);
  }
);

두번째, 세번째 인자로 콜백함수를 받아 성공과 실패를 함수로 처리한다.

  • resolve : 첫번째 인자가 숫자 일때 수행된다.
    • res === number >= 0 ? "양수" : "음수"의 결과값
  • reject : 첫번째 인자가 숫자가 아닐때 수행된다.
    • err === "주어진 값이 숫자가 아닙니다."

🔅 Promise 객체를 이용한 비동기 처리

function isPositiveP(number) {
  const executor = (resolve, reject) => {
    //실행자 -> 비동기 작업으르 실질적으로 실행하는 함수
    setTimeout(() => {
      if (typeof number === "number") {
        //성공 -> resolve
        resolve(number >= 0 ? "양수" : "음수");
      } else {
        //실패 -> reject
        reject("주어진 값이 숫자가 아닙니다.");
      }
    }, 2000);
  };

  const asyncTask = new Promise(executor);
  return asyncTask;
}

const res = isPositiveP([]); //작업 실패 : 주어진 값이 숫자가 아닙니다.
const res2 = isPositiveP(101); //작업 성공 : 양수

console.log(res); //Promise {<pending>}

res
  .then((res) => {
    console.log("작업 성공 :", res);
  })
  .catch((err) => {
    console.log("작업 실패 :", err);
  });
  • Promise객체는 함수 안에 excutor(실행하는 함수)를 선언하여 그 안에 비동기처리를 수행하는 코드를 작성한다.
  • Promise객체는 콜백함수를 사용하지 않고, then메서드와 cathc메서드를 사용하여 Promise객체의 콜백함수를 불러온다.
    • then : executor의 resolve일때
    • catch : executor의 reject일때

🔅 콜백지옥 -> Promise객체로 코드 수정 예제

콜백지옥 코드

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

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

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

//콜백 지옥
taskA(3, 4, (a_res) => {
  console.log("taskA : ", a_res);
  taskB(a_res, (b_res) => {
    console.log("taskB :", b_res);
    taskC(b_res, (c_res) => {
      console.log("taskC :", c_res);
    });
  });
});

➡️ Promise 객체를 이용해 코드를 수정

//콜백지옥 빠져나오기
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);
  });
}

//Promise객체를 통해 비동기 처리를 then과 catch를  이용해 사용하겠다는 의미로 생각해두어라

taskA(5, 1)
  .then((a_res) => {
    console.log("A RESULT : ", a_res);
    return taskB(a_res);
    //여기서 return한 값은 a_res값을 인자로 받은 taksB의 Promise객체가 반환된다.
  })
  //반환된 값이 Promise객체가 됨으로 then메서드를 이용하게 되면
  //then이 가리키는 taskB의 Promise가 된다.
  .then((b_res) => {
    console.log("B RESULT :", b_res);
    return taskC(b_res);
  })
  .then((c_res) => {
    console.log("B RESULT :", c_res);
  });

then 체이닝

then메서드를 이어서 붙여서 이용하는 것
Promise를 이용하면 코드를 아래로 보기 좋게 쓸 수 있다.
또한 then메서드 사이에 다른 작업을 수행시킬 수 도 있다.

then메서드 사이에 다른 코드 수행 예제

const bPromiseResult = taskA(5, 1).then((a_res) => {
  console.log("A RESULT : ", a_res);
  return taskB(a_res);
});

console.log("다른 코드 수행중~");
console.log("다른 코드 수행중~");
console.log("다른 코드 수행중~");
console.log("다른 코드 수행중~");

bPromiseResult
  .then((b_res) => {
    console.log("B RESULT :", b_res);
    return taskC(b_res);
  })
  .then((c_res) => {
    console.log("B RESULT :", c_res);
  });

taskB의 Promise값을 반환하는 taskA.then()~의 코드를 변수에 할당하고, 다른 코드를 수행 후에, 변수에 then메서드를 사용하게 할 수 있다.

결과값
다른 코드 수행중~
다른 코드 수행중~
다른 코드 수행중~
다른 코드 수행중~
A RESULT :  6
B RESULT : 12
B RESULT : -12
profile
기록하며 발전하는 삶

0개의 댓글