JavaScript

[새로운 기능] Promise_02 Promise 기본 사용법

  • -

이번 포스트에서는 Promise객체를 이용해서 Callback Hell에서 탈출해보자.

 

Promise

 

Promise의 상태

Promise는 총 3개의 상태를 갖는다. 최초로 Pending 상태에 있다가 fulfilledrejected 상태로 변경되고 이후 작업을 완료하거나 다른 Promise를 체이닝하여 사용할 수 있다.

  • Pending(대기): 실제 작업을 위한 준비 단계로 Promise 객체 생성 및 fulfilled, rejected 상황에서 호출할 handler 함수 바인딩한다.
  • fulfilled(이행): 동작이 성공적으로 완료된 상태이다.
  • rejected(거부): 동작이 실패한 상태이다.
  • settled(확정): pending이 아니고 fulfilled 또는 rejected 된 상태로 다음 동작 처리 가능

자료 출처: https://mdn.mozillademos.org/files/8633/promises.png

 

Promise 객체의 생성과 호출

실제 Promise 객체를 만들어보고 간단히 동작을 살펴보자.

먼저 Promise 함수는 생성자에 executor라는 함수를 파라미터로 받는데 executor는 즉시 실행되는 함수이다.

new Promise(executor)

executor는 resolver와 rejecter라는 2개의 콜백 함수를 인자로 받는데 Promise는 executor내부에서 상황에 따라 작업 성공 시 resolver를, 실패 시 rejecter를 호출하는 것을 약속한다.(확실히 호출해준다.)

 

Promise가 정상동작해서 호출되는 resolverhandler에서 사용할 값 하나를 인자로 받는다. 유사하게 Promise가 실패해서 동작하는 rejecter실패 이유(예외 원인) 하나를 인자로 받는다. resolver와 rejecter는 비동기 작업이 완료 후 확실히 호출된다.(약속했잖아~~)

간단한 Promise 객체의 동작을 살펴보자.

const p1 = new Promise((resolve, reject) => {
    const random = Math.random();
    console.log(`1. p1 execute something ${random}`);
});

console.log(p1); // pending 상태

 

Promise 객체를 생성하면 즉시 executor에 해당하는 코드(여기에 통상 비동기 코드가 작성된다.)를 실행한다. 이때 Promise의 상태는 Pending 상태이다. (현재의 예에서는 executor에서 아직 resolve나 reject를 호출하고 있지 않다. )

 

Promice의 주요 함수

promise는 3개의 instance 함수를 제공한다.

then()

(method) Promise<any>.then<void, never>(
  onfulfilled?: ((value: any) => void | PromiseLike<void>) | null | undefined, 
  onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

then()은 promise가 resolve될 때 실행할 콜백(onfulfilled)reject 될 때 실행할 콜백(onrejected)를 파라미터로 받는다. 이 콜백들은 각각 하나의 파라미터를 받는데 onfulfilled는 promise가 resolve되었을 때 전달하는 값, onrejected에는 promise가 reject된 이유가 전달된다.

then()은 반환값으로 새로운 Promise를 반환하는데 이는 Promise를 chaining 해서 사용할 수 있게 한다.

 

catch()

(method) Promise<void>.catch<void>(
    onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

catch()는 promise가 reject  될 때 실행될 콜백(onrejected)를 파라미터로 받는다. 이 콜백에는 Promise 실패의 원인이 파라미터로 전달된다.

catch()의 반환 값은 then()과 마찬가지로 새로운 Promise를 반환해서 Promise chaining이 가능하게 한다.

 

finally()

(method) Promise<void>.finally(
    onfinally?: (() => void) | null | undefined): Promise<void>

finally()는 fulfilled이든, rejected든 Promise가 종료되면 언제나 호출되는 함수이다. 따라서 then(), catch()에서 공통으로 처리해야 할 일이 있다면 이 함수에서 처리하면 된다. finally()는 파라미터가 없는 onfinally 함수를 콜백으로 받으며 Promise 객체를 반환한다.

 

활용

이제 상황에 따라 resolver, rejecter를 호출해서 연관된 handler를 동작시켜보자.

const p1 = new Promise((resolve, reject) => {
    const random = Math.random();
    console.log(`1. p1 execute something ${random}`);

    setTimeout(() => {
        if (random > 0.5) {
            resolve(random);
        } else {
            reject(random);
        }
    }, 1000);
});

const p2 = p1
    .then((val) => {
        console.log(`2. then handler ${val}`);
    })
    .catch((reason) => {
        console.log(`3. catch handler ${reason}`);
    });

console.log("4. script over");

console.log(p1); // fulfilled or rejected
console.log(p2); // pending

이제 상황에 따라서 2와 3이 호출되는데 여기서 중요한 점이 executor는 즉시 실행되고 resolve, reject는 즉시 실행되는것이 아니라 실행될 수 있는 상황에 비동기로 실행된다는 점이다. 따라서 위 코드의 실행 결과는 1 --> 4 --> (2 또는 3) 이 된다.

[다음 관련 글]

 

[새로운 기능] Promise_03 Promise 기본 사용법

이번 포스트에서는 Promise의 chaining에 대해 살펴보자. Promise의 Chaining 하지만 간단한 Promise의 사용은 기존 방식 대비 코드가 훨씬 복잡해진 느낌이다. 분명 좋다고 했는데.. then과 catch의 반환 Promise

goodteacher.tistory.com

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.