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 });
Function
)。该函数有一个参数,即接受的最终结果(the fulfillment value)。如果传入的 onFulfilled
参数类型不是函数,则会在内部被替换为(x) => x
,即原样返回 promise 最终结果的函数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
和 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.
相关链接