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

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 の定義
ドラフト  

ブラウザ実装状況

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本対応32 あり29 なし198
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
基本対応4.4.432 あり29 あり8 あり

関連情報

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

最終更新者: Uemmra3,