MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

Promiseオブジェクトは非同期処理の最終的な完了処理(もしくは失敗)およびその結果の値を表現します。

このページはPromiseのコンストラクタを説明します。Promiseについて学ぶには、Promiseを使う を最初にお読みください。通常、コンストラクタは、Promiseをまだサポートしていない関数をラップするのに使われます。

構文

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

引数

executor
2つの引数resolverejectを取る関数。executor 関数は  resolve 関数と reject 関数が渡されてPromiseが実装されるとすぐに実行されます。(Promiseコンストラクタがオブジェクトを返すよりも前にexecutorは実行されます。)  resolve 関数と reject 関数は呼び出されるとPromiseに対してそれぞれresolveもしくはrejectを行います。executorは通常、非同期の作業を開始して、完了した際に resolve 関数(成功した場合)もしくは reject 関数(エラーが発生した場合)のいずれか一方を呼び出します。

説明

Promise インターフェースは作成時点では分からなくてもよい値へのプロキシです。Promiseを用いることで、非同期アクションの成功や失敗に対するハンドラを関連付けることができます。これにより、非同期メソッドは、最終的な値を返すのではなく、未来のある時点で値を持つPromiseを返すことで、同期メソッドと同じように値を返すことができるようになります。

Promiseの状態は以下のいずれかとなります。

  • pending: 初期状態。成功も失敗もしていません。
  • fulfilled: 処理が成功して完了したことを意味します。
  • rejected: 処理が失敗したことを意味します。

pending状態のPromiseは、何らかの値を持つfulfilled状態、もしくは何らかの理由(エラー)を持つrejected状態のいずれかに変わります。そのどちらとなっても、then メソッドによって関連付けられたハンドラが呼ばれます。(対応するハンドラがアタッチされたとき、既にPromiseが成功または失敗していても、そのハンドラは呼ばれます。よって、同期処理とそのハンドラのアタッチと競合は発生しません。)

Promise.prototype.then メソッドと Promise.prototype.catch メソッドもまたPromiseを返すので、これらをチェーン(連鎖)させることができます。

混乱を避けるために: Scheme に代表されるいくつかの言語では、遅延評価や計算を延期する機構を持っており、これらも "Promise" と呼ばれます。JavaScript における Promise は、すでに起きつつある処理を表します。そしてこの処理はコールバックを使うことでチェーンさせることができます。JavaScript で遅延評価は、引数なしのアロー関数で実現できます:f = () => expression によって遅延評価される式が作成され、f を呼ぶことでその式を評価できます。

付記: Promise は fulfilled か failed のどちらかになった場合は、 pending ではなく settled と呼ばれます。また解決 (resolved) という用語も目にされたことがあると思います。解決とは、Promise の値が成功(fulfilled)したことを意味します。Domenic Denicola'の States and fates  では、Promise で使用される用語についてより詳細に述べられています。

プロパティ

Promise.length
長さを表し、常に1 (コンストラクタの引数の数)。
Promise.prototype
Promiseコンストラクタのプロトタイプを表す。

メソッド

Promise.all(iterable)
引数 iterable に含まれるPromiseについて、全てが成功したときに成功、もしくは、いずれかが失敗したときにすぐに失敗となるPromiseを返します。返されるPromiseが成功した場合は、引数 iterable に含まれる全てのPromiseが返した値をPromiseの定義順に格納された配列を値として返します。返されるPromiseが失敗した場合は、引数 iterable に含まれるPromiseのうち、最初に失敗したPromiseの理由を値として返します。このメソッドは複数のPromiseの結果を集約するのに役立ちます。
Promise.race(iterable)
引数 iterable に含まれるPromiseのうち、最初に完了 (成功または失敗) したPromiseの値を返すPromiseを返します。
Promise.reject(reason)
与えられた理由(reason)で失敗となる Promise オブジェクトを返します。
Promise.resolve(value)
与えられた値(value)で成功となる Promise オブジェクトを返します。もし値が thenable (then メソッドを持っているオブジェクト) ならば、返されるプロミスはその thenable をたどり、その結果を採用します。そうでなければ、返されるプロミスは与えられた値で成功します。一般に、ある値がPromiseかどうかがわからない場合は、Promise.resolve(value) を使ってPromiseにして扱います。

Promise プロトタイプ

プロパティ

Promise.prototype.constructor
インスタンスのプロトタイプを生成した関数を返します。デフォルトで、Promise関数です。

メソッド

Promise.prototype.catch(onRejected)
プロミスに失敗ハンドラコールバックを付加します。呼ばれるとコールバックの戻り値、または、プロミスが代わりに満たされているなら、オリジナル成功値によって完了している新しいプロミスを返します。
Promise.prototype.then(onFulfilled, onRejected)
プロミスに成功ハンドラと失敗ハンドラを付加します。呼ばれたハンドラの戻り値によって解決している新しいプロミスを返します。

Promiseを作成する

Promise オブジェクトは new キーワードとコンストラクタで作成されます。コンストラクタはexecutor関数と呼ばれる引数を取ります。executor関数は2つの関数を引数として取ります。1つめの関数 (resolve) は非同期タスクが成功して完了した場合に呼び出され、タスクの結果を値として返します。2つめの関数 (reject) はタスクが失敗した場合に呼び出され、失敗した理由(典型的にはerrorオブジェクト)を返します。

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

応用例

以下の例は Promise の仕組みを示したものです。testPromise() メソッドは <button> をクリックする度に呼び出されます。testPromise() メソッドは、 window.setTimeout() を用いて、1秒から3秒のランダムな時間の後、メソッドがこれまでに呼ばれた回数で成功するPromiseを作成します。Promise() コンストラクタは promise を作成するために使用されます。

Promiseの成功は、p1.then() で設定されたコールバックによって記録されます。この記録から、メソッドの同期処理部分が、Promiseによる非同期処理からどのように分離されているかがわかります。

'use strict';
var promiseCount = 0;

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

  var log = document.getElementById('log');
  log.insertAdjacentHTML('beforeend', thisPromiseCount + ') 開始 (<small>同期処理開始</small>)<br/>');

  // 新しいプロミスを作成: 1~3秒後に結果を返すことを約束します
  var p1 = new Promise(
    // リゾルバ関数はプロミスの成功または失敗に応じて呼ばれます
    function(resolve, reject) {
      log.insertAdjacentHTML('beforeend', thisPromiseCount + ') プロミス開始 (<small>非同期処理開始</small>)<br/>');
      // 非同期を作成するための一例です
      window.setTimeout(
        function() {
          // 約束を果たしました!
          resolve(thisPromiseCount); 
        }, Math.random() * 2000 + 1000);
    });

  // プロミスが成功した時に何をするかを定めます
  p1.then(
    // メッセージと値を記録します
    function(val) {
      log.insertAdjacentHTML('beforeend', val + ') プロミス成功 (<small>非同期処理終了</small>)<br/>');
    })
  .catch(
    // Log the rejection reason
    function(reason) {
      console.log('Handle rejected promise ('+reason+') here.');
    });

  log.insertAdjacentHTML('beforeend', thisPromiseCount + ') プロミスは作成されました (<small>同期処理終了</small>)<br/>');
}

この例はボタンをクリックすると実行されます。あなたのブラウザが Promise に対応している必要があります。短い時間の間に何度かボタンをクリックすると、それぞれのPromiseが次々と成功するのがわかります。

XHRによる画像の読み込み

PromiseXMLHttpRequestで画像を読み込む別の例は、MDN GitHub promise-testリポジトリにあり、動作を確認することができます。それぞれの行のコメントでプロミスとXHRの構造がよくわかるはずです。

仕様

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
Promise の定義
標準 Initial definition in an ECMA standard.
ECMAScript Latest Draft (ECMA-262)
Promise の定義
ドラフト  

ブラウザ互換性

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本サポート32.0(有り)29.01無し197.13
機能AndroidChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
基本サポート4.4.432.0(有り)291無し(有り)8.03

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.

関連リンク

ドキュメントのタグと貢献者

 最終更新者: ymizushi,