then() メソッドは Promise を返します。2つの引数を持ち、それらは、 Promise が成功した場合と、失敗した場合のコールバック関数です。

 片方または両方の引数が省略されるか関数でない場合、then にはハンドラーが足りていないのですが、如何なるエラーも生成されません。もしその then が呼び出されている最中の Promise が、ハンドラを持たない then の中で、状態(完了却下)を採用するのであれば、追加ハンドラの無い新しい Promise が生成され、その新しい Promise は、単に then が呼び出されている元の Promise の最終状態を採用しています。

構文

p.then(onFulfilled[, onRejected]);

p.then(function(value) {
  // fulfillment
}, function(reason) {
  // rejection
});

引数

Promise の状態に応じて、onFulfilled() または onRejected() が呼ばれます。

onFulfilled
Promise が成功したとき呼ばれるFunction。この関数は1つの引数、value を持ちます。value に渡されるのは、Promise にラップされた値などです。
onRejected Optional
Promise が失敗したとき呼ばれるFunction。この関数は1つの引数、reason を持ちます。reason は、失敗した理由などです。

Promise の解決中に例外(エラー)が発生した場合も、 onRejected が呼ばれます。

返値

Promise

  • onFulfilled() onRejected() が値を返した場合は、 Promise でラップされます。(ラップされた値は、返値 Promisethen() で取得できます。)
  • 返値 Promise の状態は、onFulfilled() onRejected() が返した値などに依存します。(どちらの関数が返したか、ではありません。)

次のものは、then メソッドの非同期性を示す例です。

// using a resolved promise, the 'then' block will be triggered instantly, 
// but its handlers will be triggered asynchronously as demonstrated by the console.logs
var resolvedProm = Promise.resolve(33);

var thenProm = resolvedProm.then(function(value){
    console.log("this gets called after the end of the main stack. the value received and returned is: " + value);
    return value;
});
// instantly logging the value of thenProm
console.log(thenProm);

// using setTimeout we can postpone the execution of a function to the moment the stack is empty
setTimeout(function(){
    console.log(thenProm);
});


// logs, in order:
// Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
// "this gets called after the end of the main stack. the value received and returned is: 33"
// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 33}

説明

then メソッドやPromise.prototype.catch()メソッドは Promise を返すので、チェーン可能です。 — composition と呼ばれる操作。

then メソッドを使う

var p1 = new Promise(function(resolve, reject) {
  resolve("Success!");
  // or
  // reject ("Error!");
});

p1.then(function(value) {
  console.log(value); // Success!
}, function(reason) {
  console.log(reason); // Error!
});

チェーン

then メソッドは Promise を返すので、メソッドチェーンができます。

関数が then にハンドラーとして渡されると Promise を返します。同じ Promise がメソッドチェーンの次の then に現れます。次のスニペットは、非同期実行をシミュレートする、 setTimout() 関数付きのコードです。

Promise.resolve("foo")
  // 1. Receive "foo" concatinate "bar" to it and resolve that to the next then
  .then(function(string) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        string += 'bar';
        resolve(string);
      }, 1);
    });
  })
  // 2. receive "foobar", register a callback function to work on that string
  // and print it to the console, but not before return the unworked on
  // string to the next then
  .then(function(string) {
    setTimeout(function() {
      string += 'baz';
      console.log(string);
    }, 1)
    return string;
  })
  // 3. print helpful messages about how the code in this section will be run
  // before string is actually processed by the mocked asynchronous code in the
  // prior then block.  
  .then(function(string) {
    console.log("Last Then:  oops... didn't bother to instantiate and return " +
                "a promise in the prior then so the sequence may be a bit " +
                "surprising");

    // Note that `string` will not have the 'baz' bit of it at this point. This 
    // is because we mocked that to happen asynchronously with a setTimeout function
    console.log(string);
});

then() の引数として渡された関数(ハンドラ)が値を返した場合は、 Promise.resolve (<ハンドラーが呼ばれて返された値>) によって、返値を自動的に Promise でラップします。

var p2 = new Promise(function(resolve, reject) {
  resolve(1);
});

p2.then(function(value) {
  console.log(value); // 1
  return value + 1;
}).then(function(value) {
  console.log(value + "- This synchronous usage is virtually pointless"); // 2- This synchronous usage is virtually pointless
});

p2.then(function(value) {
  console.log(value); // 1
});

then の引数として渡した関数が失敗状態 (rejected) の Promise が返した場合や、例外(エラー)が発生した場合は、失敗状態 (rejected) の Promise を返します。

Promise.resolve()
  .then( () => {
    // Makes .then() return a rejected promise
    throw 'Oh no!';
  })
  .then( () => { 
    console.log( 'Not called.' );
  }, reason => {
    console.error( 'onRejected function called: ', reason );
});

その他のケースでは、解決中 (resolving) の Promise  を返します。

訳注:resolving は、fate が未解決 (unresolved) という意味で使われています。fate を直訳すると運命なので、 Promise がこれからどうなるか、まだ分からないということです。 Promise で使用される用語については、 Domenic Denicola'の States and fates を参照して下さい。

次の例では、前段の Promise が失敗 (rejected) しているにも関わらず、最初の then() は、解決中の Promise でラップされた 42 を返します。

訳注:このラップされた値は、2番目の then() の、成功時に呼ばれる側のハンドラ onFulfilled() で処理されます。

Promise.reject()
  .then( () => 99, () => 42 ) // onRejected returns 42 which is wrapped in a resolving Promise
  .then( solution => console.log( 'Resolved with ' + solution ) ); // Resolved with 42

多くの場合、catch を使って失敗状態の Promise を補足する方が、then の 2 つのハンドラを使って処理するよりも現実的です。下記の例を見てください。

Promise.resolve()
  .then( () => {
    // Makes .then() return a rejected promise
    throw 'Oh no!';
  })
  .catch( reason => {
    console.error( 'onRejected function called: ', reason );
  })
  .then( () => {
    console.log("I am always called even if the prior then's promise rejects");
  });

Promise ベースの API を持った関数同士であれば、別の関数上に他の関数を実装することでチェーンを使うこともできます。

function fetch_current_data() {
  // The fetch() API returns a Promise.  This function
  // exposes a similar API, except the fulfillment
  // value of this function's Promise has had more
  // work done on it.
  return fetch("current-data.json").then((response) => {
    if (response.headers.get("content-type") != "application/json") {
      throw new TypeError();
    }
    var j = response.json();
    // maybe do something with j
    return j; // fulfillment value given to user of
              // fetch_current_data().then()
  });
}

前段の then() が Promise を返した場合、 次段の then() で、成功や失敗の処理ができます。

function resolveLater(resolve, reject) {
  setTimeout(function () {
    resolve(10);
  }, 1000);
}
function rejectLater(resolve, reject) {
  setTimeout(function () {
    reject(20);
  }, 1000);
}

var p1 = Promise.resolve("foo");
var p2 = p1.then(function() {
  // Return promise here, that will be resolved to 10 after 1 second
  return new Promise(resolveLater);
});
p2.then(function(v) {
  console.log("resolved", v);  // "resolved", 10
}, function(e) {
  // not called
  console.log("rejected", e);
});

var p3 = p1.then(function() {
  // Return promise here, that will be rejected with 20 after 1 second
  return new Promise(rejectLater);
});
p3.then(function(v) {
  // not called
  console.log("resolved", v);
}, function(e) {
  console.log("rejected", e); // "rejected", 20
});

仕様

仕様 状況 コメント
ECMAScript 2015 (6th Edition, ECMA-262)
Promise.prototype.then の定義
標準 ECMA標準における初期定義
ECMAScript Latest Draft (ECMA-262)
Promise.prototype.then の定義
ドラフト  

ブラウザ実装状況

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeEdge MobileAndroid 版 FirefoxAndroid 版 OperaiOS 版 SafariSamsung InternetNode.js
基本対応Chrome 完全対応 32Edge 完全対応 ありFirefox 完全対応 29IE 未対応 なしOpera 完全対応 19Safari 完全対応 8WebView Android 完全対応 4.4.3Chrome Android 完全対応 32Edge Mobile 完全対応 ありFirefox Android 完全対応 29Opera Android 完全対応 ありSafari iOS 完全対応 8Samsung Internet Android 完全対応 ありnodejs 完全対応 0.12

凡例

完全対応  
完全対応
未対応  
未対応

関連情報

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

最終更新者: Uemmra3,