Promise.prototype.then()

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 Latest Draft (ECMA-262)
Promise.prototype.then
Living Standard  

浏览器兼容性

No compatibility data found. Please contribute data for "javascript/promise" to the MDN compatibility data repository.


相关链接

文档标签和贡献者

 最后编辑者: HsuanLee,