promise

2 분 소요

promise

이 포스트는 JavaScript 비동기 프로그래밍에 관한 포스트입니다. 비동기처리와 관련된 설명은 링크를 참고하여 주세요.

promise란,

promise는 생성 시 꼭 알려지지 않아도 되는 proxy로써, 결과 값이나 실패 이유를 처리할 수 있게 핸들러와 연결시켜 준다. 프로미스는 비동기적 메서드를 동기적 메서드처럼 값을 리턴하게 해준다. 바로 최종 상황을 리턴하지는 않고, 프로미스를 반환하여 어떤 시점에 결과를 제공할 수 있다.

프로미스는 아래와 같은 상태 중 하나를 가지게 된다.

  • pending(대기): 이행하거나 거부되지 않은 초기상태이다.
  • fulfield(이행): 오퍼레이션이 성공적으로 완료됨.
  • rejected(거부): 오퍼레이션이 실패함.

대기 프로미스는 거부 혹은 이행상태로 진입가능하며, 이 상태로 진입하게 되면, 핸들러는 프로미스의 then 메서드에 의해 대기열에 오르게 된다. Promise.prototype.then()Promise.prototype.catch() 메서드는 다른 프로미스를 반환하므로 서로 연결할 수 있다. 이미지2

프로미스는 오브젝트 안에 오브젝트를 포함하는 특별한 형태의 자바스크립트 오브젝트로써 비동기를 강제하는 역할을 할 수 있다. 위에서 언급했 듯이 시점은 상관없으며, 어떤 경우에도 then()을 부르기만 하면 된다.

promise 사용법

const condition = true; // true면 resolve, false면 reject
const promise = new Promise((resolve, reject) => {
  if (condition) {
    resolve('성공');
  } else {
    reject('실패');
  }
});
// 다른 코드가 들어갈 수 있음
promise
  .then((message) => {
    console.log(message); // 성공(resolve)한 경우 실행
  })
  .catch((error) => {
    console.error(error); // 실패(reject)한 경우 실행
  })
  .finally(() => { // 끝나고 무조건 실행
    console.log('무조건');
  });

new Promise를 통해 프로미스 생성이 가능하며, 안에 resolve, reject를 파라미터로 갖는 콜백 함수를 넣어준다. resolve -> then, reject -> catch가 실행된다.

resolve, reject에서 파라미터는 message로 받을 것이다.

const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');
Promise.all([promise1, promise2])
  .then((result) => {
    console.log(result); // ['성공1', '성공2'];
  })
  .catch((error) => {
    console.error(error);
  });

위 코드는 프로미스 객체 여러 개를 한 번에 처리하는 방법이다.

Promise.resolve는 즉시 resolve를 하는 프로미스를 만드는 방법이다. 여러 개 있을 경우 Promise.all에 넣으면 모두 resolve될 때까지 기다렸다가 then으로 넘어간다. 하나라도 reject된다면 catch로 넘어간다.

Refernce doc 고급예제

'use strict';
var promiseCount = 0;

function testPromise() {
    var thisPromiseCount = ++promiseCount;

    var log = document.getElementById('log');
    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') 시작 (<small>동기적 코드 시작</small>)<br/>');

    // 새 프로미스 생성 - 프로미스의 생성 순서를 전달하겠다는 약속을 함 (3초 기다린 후)
    var p1 = new Promise(
        // 실행 함수는 프로미스를 이행(resolve)하거나
        // 거부(reject)할 수 있음
        function(resolve, reject) {
            log.insertAdjacentHTML('beforeend', thisPromiseCount +
                ') 프로미스 시작 (<small>비동기적 코드 시작</small>)<br/>');
            // setTimeout은 비동기적 코드를 만드는 예제에 불과
            window.setTimeout(
                function() {
                    // 프로미스 이행 !
                    resolve(thisPromiseCount);
                }, Math.random() * 2000 + 1000);
        }
    );

    // 프로미스를 이행했을 때 할 일은 then() 호출로 정의하고,
    // 거부됐을 때 할 일은 catch() 호출로 정의
    p1.then(
        // 이행 값 기록
        function(val) {
            log.insertAdjacentHTML('beforeend', val +
                ') 프로미스 이행 (<small>비동기적 코드 종료</small>)<br/>');
        })
    .catch(
        // 거부 이유 기록
        function(reason) {
            console.log('여기서 거부된 프로미스(' + reason + ')를 처리하세요.');
        });

    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') 프로미스 생성 (<small>동기적 코드 종료</small>)<br/>');
}

다음의 작은 예제는 Promise의 동작 방식을 보여줍니다. testPromise() 함수는 button을 클릭할 때마다 호출되며, window.setTimeout()을 사용해 1~3초의 무작위 간격 이후 프로미스 횟수(1부터 시작하는 숫자)로 이행하는 프로미스를 생성합니다. Promise() 생성자는 프로미스를 만드는 데 쓰입니다.

프로미스 이행은 p1.then()을 사용하는 이행 콜백 세트를 통해 단순히 로그에 남습니다. 약간의 로그를 통해, 함수의 동기 부분이 비동기적 프로미스의 완료와 어떻게 분리되어 있는지 확인할 수 있습니다.

Refernce
  • 조헌영, Node.js 교과서, 길벗, 2장 알아두어야 할 자바스크립트
  • https://medium.com/@kiwanjung/%EB%B2%88%EC%97%AD-async-await-%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90-promise%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-955dbac2c4a4
  • https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise