JavaScript参考手册
Promise
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 |
Promise相关
JavaScript 是一种高级编程语言,通过解释执行,是一门动态类型,面向对象(基于原型)的解释型语言。它已经由ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器( Chrome、IE、FireFox、Safari、Opera )支持。JavaScript 是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持 I/O,比如网络