[JS]promise

Hyoyoung Kim·2022년 8월 18일
0

React TIL

목록 보기
13/40

콜백지옥

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

Promise

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

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

1. Pending(대기상태)

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

2. Fulfilled(성공)

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

3. Rejected(실패)

거부, 실패
비동기 작업이 실행이 실패된 상태이며 서버가 응답이 없거나, 시간이 오래 걸릴때 자동으로 실행이 취소되는 상태.
비동기 작업은 한 번 실패하거나 성공하면 작업이 끝난다.

resolve와 reject

1. resolve 해결 : pending -> Fullfilled

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

2. reject 거부 : Pending -> Rejected

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

promise 예시1

콜백을 이용한 숫자값 알아보는 함수(콜백지옥)


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);
  }
);]

함수 실행 흐름

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);
  //*위 코드를 설면하자면*
  //비동기작업 자체인 promise를 저장할 상수 asyncTask를 만들어주고 
  // new 키워드를 사용하여 Promise객체를 생성하면서
  //Promise객체의 생성자로 비동기작업의 실질적인 실행적인 함수(exector)을 넘겨주게 되면
  //exector함수가 바로 실행된다.
  
  //즉, exector을 담은 Promise 객체를 상수 asyncTask에 담아주었다. 
  
  return asyncTask;
   //**어떤 함수가 promise를 반환한다는 것은 이 함수는 비동기 작업을 하고 그 결과를 
  //promise 객체로 반환받아서 사용할 수 있는 함수라는 것을 뜻한다.**
}


// isPositiveP함수가 반환하는 promise 객체를 res라는 상수에 저장한다.
const res = isPositiveP([]); //작업 실패 : 주어진 값이 숫자가 아닙니다.
// []는 number가 아니므로 resolve를 지나가 reject의 값이 나오게 된다. 


const res2 = isPositiveP(10); //작업 성공 : 양수

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

//**pending인 이유**
//코드에서는 promise객체를 반환하게만 할뿐, 실행이 되진 않았기 때문에 결과 값에 
//pending(대기)상태의 Promise 객체만 남아있는 것이다. 


//*promise객체의 비동기처리의 '결과'를 사용하는 방법*
//res.then(()=>{}).catch(()=>{})
//then : executor의 resolve일때
//catch : executor의 reject일때
res
  .then((res) => {
    console.log("작업 성공 :", res);
  })
  .catch((err) => {
    console.log("작업 실패 :", err);
  });

함수 실행 흐름

promise 예시2

콜백지옥

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);
      // resolve와 reject를 받았기 떄문에 cd는 필요없다. 
    }, 3000);
  });
}

//위의 코드를 다르게 표현하자면?
//function taskA(a, b) {
// const executorA=(resolve, reject) => {
//    setTimeout(() => {
//      const res = a + b;
//      resolve(res);
//    }, 3000);
//  };

//return new Promise(executorA)
//}

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);
  //c의 promise를 받는다.  
  })
  .then((c_res) => {
    console.log("B RESULT :", c_res);
  });

then 체이닝

then메서드를 이어서 붙여서 이용하는 것.
then메서드 사이에 다른 작업을 수행시킬 수 도 있다.

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

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

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);
  });

//**결과**

//다른 코드 
//다른 코드 
//A RESULT :  6
//B RESULT : 12
//B RESULT : -12

0개의 댓글