본문 바로가기
PL (Programming Language)/JavaScript

[JS] 자바스크립트 비동기 객체 Promise: resolve - then, reject - catch

by jangThang 2023. 9. 27.
반응형

 자바스크립트에서 비동기 실행을 할 때 사용하는 promise객체에 대해서 알아봅니다. promise 객체는 실행 대기, 실행 성공, 실행 실패 상태를 가지며 각 상태에 따라 다른 콜백함수를 호출합니다.

 

[ Contents ]

     

     

    1. Callback 지옥

    const workA = (value, callback) => {
      setTimeout(() => {
        console.log('A실행');
        callback(value + 5);
      }, 500);
    };
    const workB = (value, callback) => {
      setTimeout(() => {
        console.log('B실행');
        callback(value - 3);
      }, 300);
    };
    const workC = (value, callback) => {
      setTimeout(() => {
        console.log('C실행');
        callback(value + 10);
      }, 1000);
    };
    const workD = (value, callback) => {
        console.log('D실행');
        callback(value);
    };
    
    workA(10, (resA) => {
      console.log(`1. ${resA}`);
      workB(resA, (resB) => {
        console.log(`2. ${resB}`);
        workC(resB, (resC) => {
          console.log(`3. ${resC}`);
        });
      });
    });
    workD("workD", (res) => {
      console.log(res);
    });

     콜백 지옥은 '콜백 함수'가 꼬리에 꼬리를 물고 계속 늘어지는 코드를 말합니다. 

     자바스크립트는 setTimeout과 같은 비동기 함수를 통해 멀티 쓰레드를 구현합니다. 하지만 비동기로 실행할 때도 '순차적으로 실행'되어야 하는 코드가 있습니다. 이를 콜백함수로 호출해서 순서를 강제하곤 합니다.

     예를 들어 작업이나 이벤트가 끝난 뒤 메시지나 로그를 쌓을 때 주로 사용합니다. 특히 연쇄적으로 작업이 처리되어야 하는 트랜잭션을 수행할 때도 이용되는데, 이 경우에는 콜백 지옥이 생길 위험이 높습니다.

     

     

     

    2. Promise 객체

    const func = (resolve, reject) => {
        setTimeout(() => {
            console.log("3초 대기");
            resolve();
        }, 300);
    };
    
    const promise = new Promise(func);
    promise.then(() => {
        console.log("종료");
      });

     자바스크립트에서 비동기를 간편하게 처리하기 위해 만든 내장 객체입니다.

     callback으로 함수를 인수로 전달받지 않으며, 작업의 성공/실패 여부에 따라 실행할 콜백함수를 분기할 수 있습니다.

     

    const work = (callback) => {
      setTimeout(() => {
        console.log("3초 대기");
        callback();
      }, 300);
    };
    
    work(() => {
        console.log("종료");
    });

     콜백함수로 구현한 코드입니다. 단순한 코드의 경우, 콜백함수로 구현해도 문제가 되진 않습니다.

     다만 작업의 성공/실패 여부에 따라 분기가 필요하고, 여러 작업이 연이어 진행되어야 한다면 1번과 같은 콜백지옥이 탄생합니다.

     

    2023.09.25 - [PL (Programming Language)/JavaScript] - [JS] 자바스크립트 동기와 비동기: 쓰레드(Thread)와 콜백함수(Callback)

     

    [JS] 자바스크립트 동기와 비동기: 쓰레드(Thread)와 콜백함수(Callback)

    자바스크립트의 동기와 비동기 작업에 대해 알아보겠습니다. [ Contents ] 1. 자바스크립트 동기 순차적으로 작업이 실행되는 방식 코드가 실행되는 통상적인 방식입니다. console.log("a"); console.log("b"

    star7sss.tistory.com

     

     

    반응형

     

    3. resolve와 reject

    resolve: 작업 성공 시 실행
    reject: 작업 실패 시 실행

     

     promise 객체는 3가지 상태를 갖습니다.

     실행 전 대기상태(pedding), 성공(fullfilled), 실패(rejected)로 나뉩니다. resolve가 실행되면 성공이고, reject가 실행되면 실패로 취급하죠. 흔히 실행결과 res = 0[false] or 1[true]를 반환해서 성공과 실패를 분기하는 방식과 유사합니다.

     

    then: resolve의 콜백함수
    catch: reject의 콜백함수

     

     실행이 성공했다면 then 메서드가 실행되며, 실패했다면 catch 메서드가 실행됩니다.

     

    const func = (resolve, reject) => {
        setTimeout(() => {
            reject();
        }, 300);
    };
    
    const promise = new Promise(func);
    promise
      .then(() => {
        console.log("성공");
      })
      .catch(() => {
        console.log("실패");
      });

     위 예제에서는 reject() 메서드가 실행되었으므로, promise 객체의 상태는 실패(rejected)입니다. 따라서 then은 무시되고 catch만 실행됩니다.

     

     

     

    4. 프로미스 체이닝 (Promise Chaining)

    const workA = (value) => {
      const promise = new Promise((resolve) => {
        setTimeout(() => {
          console.log('A실행');
          resolve(value + 5);
        }, 500);
      });
      return promise;
    };
    
    const workB = (value) => {
      const promise = new Promise((resolve) => {
        setTimeout(() => {
          console.log('B실행');
          resolve(value - 3);
        }, 300);
      });
      return promise;
    };
    
    const workC = (value) => {
      const promise = new Promise((resolve) => {
        setTimeout(() => {
          console.log('C실행');
          resolve(value + 10);
        }, 1000);
      });
      return promise;
    };
    
    const workD = (value, callback) => {
        console.log('D실행');
        callback(value);
    };
    
    workA(10)
      .then((resA) => {
        console.log(`1. ${resA}`);
        return workB(resA);
      })
      .then((resB) => {
        console.log(`2. ${resB}`);
        return workC(resB);
      })
      .then((resC) => {
        console.log(`3. ${resC}`);
      })
      .catch((error) => {
        console.log(error);
      });
    
    workD("workD", (res) => {
      console.log(res);
    });

     프로미스 객체를 이용해서 연이어 실행하는 코드를 '프로미스 체이닝'이라고 합니다.

     1번에서 다룬 콜백지옥을 프로미스 객체를 사용해서 바꾸면 위와 같습니다. 절대적인 코드량은 비슷하지만, 가독성은 좋습니다. 물론 이것도 그나마 낫다에 가깝지, 좋은 편은 아니긴 합니다.

     그래서 async와 aswait문법이 추가적으로 도입되었으며 해당 문법은 다음 글에서 알아보겠습니다.

     

    star가 되고나서 Tistory

    반응형

    댓글