promise.then
promise.then
then()
方法返回一个 Promise
。它最多需要有两个参数:Promise
的成功和失败情况的回调函数。
如果忽略针对某个状态的回调函数参数,或者提供非函数 (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)。onRejected当Promise变成拒绝状态(rejection )时,该参数作为回调函数被调用(参考: Function
)。该函数有一个参数,,即拒绝的原因(the rejection reason)
。
返回值
then方法返回一个Promise
,而它的行为与then中的回调函数的返回值有关:
- 如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
- 如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
- 如果then中的回调函数返回一个已经是接受状态的Promise,那么then返回的Promise也会成为接受状态,并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
- 如果then中的回调函数返回一个已经是拒绝状态的Promise,那么then返回的Promise也会成为拒绝状态,并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
- 如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。
以下举例说明该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( (resolve, reject) => {
resolve('Success!'
// or
// reject ("Error!"
}
p1.then( value => {
console.log(value // Success!
}, reason => {
console.log(reason // Error!
}
链式调用
then
方法返回一个Promise
对象,其允许方法链。
你可以传递一个 lambda 给 then 并且如果它返回一个 promise,一个等价的 Promise 将暴露给后续的方法链。下面的代码片段使用 setTimout 函数来模拟异步代码操作。
Promise.resolve('foo')
// 1. Receive "foo", concatenate "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 returning 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 the string is actually processed by the mocked asynchronous code in the
// previous 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(<由被调用的处理程序返回的值>)。
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( () => {
// Makes .then() return a 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( () => {
// 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-based 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()
}
}
如果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
}
规范
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'Promise.prototype.then' in that specification. | Standard | Initial definition in an ECMA standard. |
ECMAScript Latest Draft (ECMA-262)The definition of 'Promise.prototype.then' in that specification. | Living Standard | |
浏览器兼容性
Feature | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic Support | 32.0 | (Yes) | 29.0 | No | 19 | 7.1 |
Feature | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
Basic Support | 4.4.4 | 32.0 | (Yes) | 29 | No | (Yes) | 8.0 |