MDN wants to talk to developers like you: https://qsurvey.mozilla.com/s3/8d22564490d8

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

注意事项:如果省略这两个参数,或者提供非函数,那么将创建一个没有其他处理程序的新Promise,只是采用 Promise 的最终状态,then 被调用。如果省略第一个参数或提供的不是函数,创建的新 Promise 简单地采用 Promise 的完成状态,then被调用(如果它变为完成)。如果省略第二个参数或提供的不是函数,创建的新 Promise 简单地采用 Promise 的拒绝状态,then被调用(如果它被拒绝)。

语法

p.then(onFulfilled, onRejected);

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

参数

then 返回一个由输入函数确定的Promise:

  • 如果 onFulfilled  或者 onRejected 抛出一个错误,或者返回一个拒绝的 Promise ,then 返回一个 rejected Promise
  • 如果 onFulfilled  或者 onRejected 返回一个 resolves Promise,或者返回任何其他值,then 返回一个 resolved Promise
onFulfilled
一个 Function被调用, 当 Promise 满足时. 该函数有一个参数,即 fulfillment 值。
onRejected
一个 Function被调用, 当 Promise 被拒绝时. 该函数有一个参数, 拒绝的 reason

返回值

一个 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" 拼接,并将其结果做为下一个reslove返回。
  .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.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 2017 Draft (ECMA-262)
Promise.prototype.then
Draft  

浏览器兼容性

Feature Chrome Edge Firefox Internet Explorer Opera Safari Servo
Basic Support32.0(Yes)29.0No support197.1No support
Feature Android Chrome for Android Edge Mobile Firefox for Android IE Mobile Opera Mobile Safari Mobile
Basic Support4.4.432.0(Yes)29No support(Yes)8.0


相关链接

文档标签和贡献者

 最后编辑者: HsuanLee,