`then()` 方法返回一个 `Promise` 。它最多需要有两个参数：Promise 的成功和失败情况的回调函数。

The source for this interactive demo is stored in a GitHub repository. If you'd like to contribute to the interactive demo project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

注意：如果忽略针对某个状态的回调函数参数，或者提供非函数 (nonfunction) 参数，那么 `then` 方法将会丢失关于该状态的回调函数信息，但是并不会产生错误。如果调用 `then` 的 `Promise` 的状态（fulfillment 或 rejection）发生改变，但是 `then` 中并没有关于这种状态的回调函数，那么 `then` 将创建一个没有经过回调函数处理的新 `Promise` 对象，这个新 `Promise` 只是简单地接受调用这个 `then` 的原 `Promise` 的终态作为它的终态。

## 语法

    p.then(onFulfilled, onRejected);

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

### 参数

onFulfilled
  当Promise变成接受状态（fulfillment）时，该参数作为回调函数被调用（参考： `Function`）。该函数有一个参数，即接受的最终结果（the fulfillment value）。如果传入的 `onFulfilled` 参数类型不是函数，则会在内部被替换为`(x) => x` ，即原样返回 promise 最终结果的函数
onRejected
  当Promise变成拒绝状态（rejection ）时，该参数作为回调函数被调用（参考： `Function`）。该函数有一个参数,，即拒绝的`原因（the rejection reason）`。

    var p = new Promise((resolve, reject) => {
        resolve('foo')
    })

    // 'bar' 不是函数，会在内部被替换为 (x) => x
    p.then('bar').then((value) => {
        console.log(value) // 'foo'
    })

### 返回值

当一个`Promise`完成（fulfilled）或者失败（rejected），返回函数将被异步调用（由当前的线程循环来调度完成）。具体的返回值依据以下规则返回：

- 如果then中的回调函数返回一个值，那么then返回的Promise将会成为接受状态，并且将返回的值作为接受状态的回调函数的参数值。
- 如果then中的回调函数没有返回值，那么then返回的Promise将会成为接受状态，并且该接受状态的回调函数的参数值为 undefined。
- 如果then中的回调函数抛出一个错误，那么then返回的Promise将会成为拒绝状态，并且将抛出的错误作为拒绝状态的回调函数的参数值。
- 如果then中的回调函数返回一个已经是接受状态的Promise，那么then返回的Promise也会成为接受状态，并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
- 如果then中的回调函数返回一个已经是拒绝状态的Promise，那么then返回的Promise也会成为拒绝状态，并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
- 如果then中的回调函数返回一个未定状态（pending）的Promise，那么then返回Promise的状态也是未定的，并且它的终态与那个Promise的终态相同；同时，它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。

## 描述

由于 `then` 和 `Promise.prototype.catch()` 方法都会返回 promise，它们可以被链式调用 — 一种称为复合（ composition） 的操作.

## 示例

### `使用then方法`

    let 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 对象，其允许方法链。

你可以传递一个 lambda 给 then 并且如果它返回一个 promise，一个等价的 Promise 将暴露给后续的方法链。下面的代码片段使用 setTimout 函数来模拟异步代码操作。

    Promise.resolve("foo")
      // 1. 接收 "foo" 并与 "bar" 拼接，并将其结果做为下一个resolve返回。
      .then(function(string) {
        return new Promise(function(resolve, reject) {
          setTimeout(function() {
            string += 'bar';
            resolve(string);
          }, 1);
        });
      })
      // 2. 接收 "foobar", 放入一个异步函数中处理该字符串
      // 并将其打印到控制台中, 但是不将处理后的字符串返回到下一个。
      .then(function(string) {
        setTimeout(function() {
          string += 'baz';
          console.log(string);
        }, 1)
        return string;
      })
      // 3. 打印本节中代码将如何运行的帮助消息，
      // 字符串实际上是由上一个回调函数之前的那块异步代码处理的。
      .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");

        // 注意 `string` 这时不会存在 'baz'。
        // 因为这是发生在我们通过setTimeout模拟的异步函数中。
        console.log(string);
    });

当一个值只是从一个 lambda 内部返回时，它将有效地返回 Promise.resolve（<由被调用的处理程序返回的值>）。

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

如果函数抛出错误或返回一个拒绝的Promise，则调用将返回一个拒绝的Promise。

    Promise.resolve()
      .then( () => {
        // 使 .then() 返回一个 rejected promise
        throw 'Oh no!';
      })
      .then( () => {
        console.log( 'Not called.' );
      }, reason => {
        console.error( 'onRejected function called: ', reason );
    });

在其他情况下，一个 resolving Promise 会被返回。在下面的例子里，第一个 then() 会返回一个用 resolving Promise 包装的 42，即使之前的 Promise 是 rejected 的。

    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

实际上，捕获 rejected promise 的需求经常大于使用 then 的两种情况语法，比如下面这样的：

    Promise.resolve()
      .then( () => {
        // 使 .then() 返回一个 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-based API 的函数。

    function fetch_current_data() {
      // fetch() API 返回了一个 Promise.
      // 这个函数提供了类似的API，
      // 这个函数除了实现 Promise，它还能够完成更多的工作。
      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()
      });
    }

如果 `onFulfilled` 返回了一个 promise，`then` 的返回值就会被 Promise resolved或者rejected。

    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 | Standard | ECMA标准的首次定义
ECMAScript Latest Draft (ECMA-262) Promise.prototype.then | Draft |

## 浏览器兼容性

No compatibility data found. Please contribute data for "javascript/promise" (depth: Promise.prototype.then) to the MDN compatibility data repository.

相关链接

- `Promise`
- `Promise.prototype.catch()`