We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

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 関数(エラーが発生した場合)のいずれか一方を呼び出します。executor 関数でエラーが投げられた場合、Promise は reject されます。executor の返り値は無視されます。

説明

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 が解決または他の promise の状態にマッチするために" locked in "したことを意味します。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 かどうかがわからない場合は、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() {
    let thisPromiseCount = ++promiseCount;

    let log = document.getElementById('log');
    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') 開始 (同期処理開始)
');

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

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

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

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

XHR による画像の読み込み

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

仕様

仕様書 策定状況 コメント
ECMAScript 2015 (6th Edition, ECMA-262)
Promise の定義
標準 ECMA 標準での初期定義。
ECMAScript Latest Draft (ECMA-262)
Promise の定義
ドラフト  

ブラウザー実装状況

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
Promise32 あり291 なし1983
all32 あり29 なし198
prototype32 あり29 なし198
catch32 あり29 なし198
finally63 なし58 なし50 なし
then32 あり29 なし198
race32 あり29 なし198
reject32 あり29 なし198
resolve32 あり29 なし198
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Promise4.4.432 あり291 あり83 あり
all4.4.432 あり29 あり8 あり
prototype4.4.432 あり29 あり8 あり
catch4.4.432 あり29 あり8 あり
finally6363 なし5850 なし なし
then4.4.432 あり29 あり8 あり
race4.4.432 あり29 あり8 あり
reject4.4.432 あり29 あり8 あり
resolve4.4.432 あり29 あり8 あり

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.

関連情報

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

最終更新者: Uemmra3,