Promise 개체는 비동기 작업의 최종 완료 (또는 실패)와 결과 값을 나타냅니다. 

여기서는 Promise constructor를 다룹니다. promises에 대해 알아보려면 Using promises 를 먼저 읽어보세요 . constructor는 주로 promises를 지원하지 않는 함수를 래핑하는 데 사용됩니다.

구문

new Promise( /* executor */ function(resolve, reject) { ... } );

매개변수

executor
resolvereject 인수와 함께 전달되는 함수입니다. Executor 함수는 Promise 구현에 의해 즉시 실행되고 resolvereject 함수를 전달합니다 (Executor는 Promise 생성자가 생성 된 객체를 반환하기 전에 호출됩니다). resolve 및 reject 기능은 호출 될 때 마다 promise를 해결(resolve)하거나 거부(reject)합니다. Executor는 보통 몇몇 비동기(asynchronous) 작업을 시작한 다음 이것이 완료되었을 때 resolve 함수를 호출하여 promise를 해결하거나 오류가 발생하면 거부(reject)합니다.
executor 함수에서 오류가 발생하면 promise는 거부(rejected)됩니다. executor의 반환값은 무시됩니다.

설명

Promise는 프로미스가 생성될 때 꼭 알 필요는 없는 값을 위한 대리자입니다. 이는 비동기 동작이 종료된 이후의 결과값이나 실패 이유를 처리하기 위한 처리기(handler)를 연결할 수 있도록 합니다. 프로미스는 비동기 메서드가 동기 메서드처럼 값을 반환하도록 합니다. 최종값 대신, 비동기 메서드는 미래 어느 시점에 값을 갖는 promise를 반환합니다.

Promise는 다음 중 하나의상태를 가집니다.

  • 대기중(pending): 초기 상태, 이행 또는 거부되지 않은.
  • 이행됨(fulfilled): 연산이 성공리에 완료되었음을 뜻합니다.
  • 거부됨(rejected): 연산이 실패했음을 뜻합니다.

대기중인 promise는 값으로 이행(fulfilled)되거나, 어떤 이유(error)와 함께 거부될 수 있습니다. 이 중 하나가 일어난 경우, 연결된 처리기는 호출된 프로미스의 then 메서드에 의해 대기열에 오릅니다(queued up). (프로미스에 핸들러가 붙을 때 이미 이행 또는 거부된 경우에도 처리기는 호출되므로, 비동기 연산과 부착될 핸들러 사이에는 경합 조건(race condition)이 없습니다.)

Promise.prototype.then()Promise.prototype.catch() 메서드가 프로미스를 반환하기에, 둘은 연결(chain)될 수 있습니다

혼동하지 않도록 하세요: 여러 다른 언어(가령 Scheme)에는 게으른(lazy) 평가 및 계산을 연기하기 위한 메커니즘이 있는데 그들도 “promise”라고 부릅니다. JavaScript에서 프로미스는 이미 생긴 프로세스를 나타내고, 이는 콜백 함수로 연결(chain)될 수 있습니다. 당신이 식(expression)을 게으르게 평가할 길을 찾고 있는 경우, 게으르게 평가되는 식을 만들기 위한 인수 없는 화살표 함수: f = () => expression 와 평가하는 f()를 고려하세요.

주의: 프로미스는 대기중이 아니라 이행 또는 거부된 경우 처리되었다(settled)고 합니다. 또한 프로미스와 함께 쓰이는 용어 (운명이) 결정됨(resolved)도 듣기 마련입니다 — 이는 프로미스가 (상태가) 처리됨(settled) 또는 프로미스 (처리) 체인 내에 갇힘(locked)을 뜻합니다. 프로미스 용어에 관한 더 자세한 사항은 Domenic Denicola의 글 상태와 운명에 담겨 있습니다.

속성

Promise.length
값이 언제나 1인 Length 속성입니다. (생성자 인수의 수를 나타냅니다.)
Promise.prototype
Promise 생성자의 프로토타입을 나타냅니다.

메서드

Promise.all(iterable)
인수 iterable 내의 모든 프로미스가 결정된 때 결정되며 하나의 프로미스라도 거부된 경우 즉시 거부하는 프로미스를 반환합니다. 이 프로미스가 결정되는 경우, iterable 내의 프로미스가 결정한 값들의 배열로 결정됩니다. 반환된 프로미스가 거부되는 경우, iterable 내의 거부된 그 프로미스가 거부된 이유를 그대로 이용해 거부합니다. 이 메서드는 여러 프로미스의 결과를 모두 모으는 데 유용할 수 있습니다.
Promise.race(iterable)
iterable 내 프로미스 중 하나를 결정 또는 거부하자마자 결정 또는 거부하는 프로미스를 반환합니다, 그 프로미스로부터 값 또는 이유로.
Promise.reject(reason)
주어진 reason(이유)로 거부된 Promise 객체를 반환합니다.
Promise.resolve(value)
주어진 값(value)으로 결정된 Promise 객체를 반환합니다. 값이 thenable 객체인(즉 then 메서드가 있는) 경우, 반환된 프로미스는 그 thenable을 "따르고(follow)", 그 최종 상태를 취합니다; 그렇지 않으면 반환된 프로미스는 그 값으로 이행됩니다. 보통, 값이 프로미스인지 아닌지 알고 싶은 경우 - 대신 Promise.resolve(value)로 쓰고 프로미스처럼 반환값으로 작동합니다.

Promise 프로토타입

속성

Promise.prototype.constructor
인스턴스의 프로토타입을 만드는 함수를 반환합니다. 이는 기본으로 Promise 함수입니다.

메서드

Promise.prototype.catch(onRejected)
프로미스(promise)에 거부 처리기 콜백을 추가하고 호출된 경우 콜백의 반환값 또는 프로미스가 대신 이행된 경우 그 원래 이행(fulfillment)값으로 결정하는(resolving) 새 프로미스를 반환합니다.
Promise.prototype.then(onFulfilled, onRejected)
프로미스에 이행 또는 거부 처리기를 추가하고 호출된 처리기의 반환값 또는 프로미스가 처리되지 않은 경우 그 원래 처리된(settled) 값으로 결정하는 새 프로미스를 반환합니다 (즉 관련 처리기 onFulfilled 또는 onRejectedundefined인 경우).

promise 생성하기

Promise 오브젝트는 new 키워드와 생성자를 사용하여 민듭니다. 이 생성자는 인수로 "executor 함수"라는 함수를 사용합니다. 이 함수는 매개 변수로 두 가지 함수를 가져야 합니다. asynchronous 태스크가 성공적으로 완료되고 태스크의 결과를 값으로 리턴하면 첫 번째 함수(resolve)가 호출됩니다. 두 번째 (reject)는 작업이 실패 할 때 호출되며 보통 오류 객체를 반환합니다.

const myFirstPromise = new Promise((resolve, reject) => {
  // do something asynchronous which eventually calls either:
  //
  //   resolve(someValue); // fulfilled
  // or
  //   reject("failure reason"); // rejected
});

promise 기능을 제공하려면 promise를 반환하면됩니다.

function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
}

예제

기본 예제

let myFirstPromise = new Promise((resolve, reject) => {
  // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
  // In this example, we use setTimeout(...) to simulate async code. 
  // In reality, you will probably be using something like XHR or an HTML5 API.
  setTimeout(function(){
    resolve("Success!"); // Yay! Everything went well!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  // successMessage is whatever we passed in the resolve(...) function above.
  // It doesn't have to be a string, but if it is only a succeed message, it probably will be.
  console.log("Yay! " + successMessage);
});

고급 예제

<button id="btn">Make a promise!</button>
<div id="log"></div>

이 간단한 예는 Promise의 메커니즘을 보여줍니다. testPromise() 메서드는 <button>이 클릭될 때마다 호출됩니다. window.setTimeout()을 사용하여 1-3 초마다 promise count (1부터 시작하는 숫자)까지 무작위로 promise를 만듭니다., Promise() 생성자는 프로미스를 만드는 데 쓰입니다.

프로미스 fulfillment는 p1.then()을 사용하는 fulfill callbqck 세트를 통해 간단하게 기록(log)됩니다. 약간의 로그는 메서드의 동기 부분이 promise의 비동기 완료(completion)와 분리(decouple)되는 것을 보여줍니다.

'use strict';
var promiseCount = 0;

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

    var log = document.getElementById('log');
    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Started (<small>Sync code started</small>)<br/>');

    // 새 약속을 (생성)합니다: 이 프로미스의 숫자 셈을 약속합니다, 1부터 시작하는(3s 기다린 뒤)
    var p1 = new Promise(
        // resolver(결정자) 함수는 프로미스 (이행을) 결정 또는 거부하는
        // 능력과 함께 호출됩니다
        function(resolve, reject) {
            log.insertAdjacentHTML('beforeend', thisPromiseCount +
                ') Promise started (<small>Async code started</small>)<br/>');
            // 이는 비동기를 만드는 예에 불과합니다
            window.setTimeout(
                function() {
                    // 프로미스 이행 !
                    resolve(thisPromiseCount);
                }, Math.random() * 2000 + 1000);
        }
    );

    // 프로미스가 then() 호출로 결정된/이행된 경우 무엇을 할 지를 정의하고,
    // catch() 메서드는 프로미스가 거부된 경우 무엇을 할 지를 정의합니다.
    p1.then(
        // 이행값 기록
        function(val) {
            log.insertAdjacentHTML('beforeend', val +
                ') Promise fulfilled (<small>Async code terminated</small>)<br/>');
        })
    .catch(
        // 거부 이유 기록
        function(reason) {
            console.log('Handle rejected promise ('+reason+') here.');
        });

    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Promise made (<small>Sync code terminated</small>)<br/>');
}

 

if ("Promise" in window) { 
  var btn = document.getElementById("btn"); 
  btn.addEventListener("click",testPromise); 
} else { 
  log = document.getElementById('log');
  log.innerHTML = "Live example not available as your browser doesn't support the <code>Promise<code> interface."; 
}

이 예제는 버튼을 클릭하면 실행됩니다. Promise를 지원하는 브라우저가 필요합니다. 짧은 시간 안에 버튼을 여러 번 클릭하여, 서로 다른 프로미스가 번갈아 이행되는 것을 볼 수도 있습니다.

XHR로 이미지 로딩

이미지를 로드하기 위해 PromiseXMLHttpRequest를 사용하는 또 다른 간단한 예는 MDN GitHub js-examples 저장소에서 이용할 수 있습니다. 실제 예를 볼 수도 있습니다. 각 단계는 주석이 있어 프로미스 및 XHR 구조를 철저히 따르도록 해줍니다.

Specifications

스펙 상태 설명
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Promise' in that specification.
Standard ECMA 표준에서 초기 정의.
ECMAScript Latest Draft (ECMA-262)
The definition of 'Promise' in that specification.
Draft  

브라우저 호환성

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Promise32 Yes291 No1983
all32 Yes29 No198
prototype32 Yes29 No198
catch32 Yes29 No198
finally63 No58 No50 No
then32 Yes29 No198
race32 Yes29 No198
reject32 Yes29 No198
resolve32 Yes29 No198
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Promise4.4.432 Yes291 Yes83 Yes
all4.4.432 Yes29 Yes8 Yes
prototype4.4.432 Yes29 Yes8 Yes
catch4.4.432 Yes29 Yes8 Yes
finally6363 No5850 No No
then4.4.432 Yes29 Yes8 Yes
race4.4.432 Yes29 Yes8 Yes
reject4.4.432 Yes29 Yes8 Yes
resolve4.4.432 Yes29 Yes8 Yes

1. Constructor requires a new operator since version 37.

2. Constructor requires a new operator since version 4.

3. Constructor requires a new operator since version 10.

 

참조

문서 태그 및 공헌자

최종 변경: earyomee,