JS Promise.prototype.then()
then()
方法为 Promise
实例添加状态改变时的回调函数,并返回一个新的 Promise
实例。
then()
方法的支持传入一个(或两个)参数,作为 Promise
实例 状态转为成功或失败的回调函数。
// ...假定 getJSON(url) 调用服务器请求json文本,并返回一个Promise实例
function fullFilled(json){
console.log('远程数据调用成功');
}
function rejected(err){
console.log('远程结果调用失败');
}
getJSON("/posts.json").then(fullFilled, rejected);
语法:
Promise.prototype.then(onFulfilled, onRejected);
参数:
参数 | 类型 | 描述 |
---|---|---|
onFulfilled | Function | Promise 实例状态由pending 变成fulfilled 状态时将调用此回调函数。该函数将接收一个参数value ,这个参数值由 Promise 实例内部的resolve(value) 函数传出。 |
onRejected | Function | 选填。Promise 实例状态由pending 变成reject 状态时调用的回调函数。该函数将接收一个参数value ,这个参数值由 Promise 实例内部的reject(value) 函数传出。 |
返回值:
返回新的 Promise
实例。
then() - 使用示例
/*
* 模拟抛硬币的小游戏:
* 生成一个随机数(值范围0-1),大于0.5表示正面,否则表示反面,硬币在抛出后第二秒静止
*/
function coinFlips(){
return new Promise((resolve, reject) => {
setTimeout(() => {
var n = Math.random();
n > 0.5 ? resolve(n) : reject(n);
}, 2000);
})
}
coinFlips()
.then(function(value) {
/*
* 当Promise实例状态变为fullfilled,将执行此回调函数
* Promise内部的resolve(n)传入的值n将被这里的value接收
*/
console.log(`硬币是正面,随机值等于:${value}`);
}, function(value) {
/*
* 当Promise状态变为reject,将执行此回调函数
* Promise内部的reject()传入的的值n将被这里的value接收
*/
console.log(`硬币是反面,随机值等于:${value}`);
})
// 2秒后输出随机结果...
then() - 链式调用
上面我们提到,then()
返回一个新的 Promise
实例,这个实例同样拥有then()
方法,因此,我们可以链式地调用 then()
方法:then(...).then(...).then(...)
。
前一个then()
传入的回调函数返回一个非Promise实例的值时,该值将直接被后一个then()方法
的回调函数接收。
var p = function(){
return new Promise(function(resolve, reject){
resolve('Hello Promise');
})
};
p().then(function(value) {
console.log(value);
return String.prototype.toUpperCase.call(value); // return 的值并非Promise实例,直接被下一个then()的回调参数接收
})
.then(function(value) {
console.log(value);
})
// 输出 "Hello Promise"
// 输出 "HELLO PROMISE"
前一个then()
传入的回调函数返回一个Promise实例时,后一个then()
传入的的回调函数接收到的值取决于这个Promise实例的状态变化。
var p1 = function(){
return new Promise(function(resolve, reject){
resolve('success');
})
};
var p2 = function(){
return new Promise(function(resolve, reject){
reject('failed');
})
};
p1().then(function(value) {
console.log(value);
return p2(); // return 的值是Promise实例,下一个then()的回调参数将由这个实例的状态决定。
})
.then(function(value) {
console.log(value);
}, function(value) {
console.log(value);
});
// 输出 "success"
// 输出 "failed"
上面的例子中,第一个then()
的回调函数参数返回的是一个 Promise实例
,第二个then()
执行哪个回调函数参数将取决于p2()
的状态,并接收 p2()
传出的值。
传入then()
的回调函数内部报错时,返回的Promise实例状态转为reject
var p = function(){
return new Promise(function(resolve, reject){
resolve('success');
})
};
p()
.then(function() {
// 写一段错误的代码:打印一个未定义的变量
console.log(a);
})
.then(function() {
//上面的代码发生错误,所以不会执行这里的代码
}, function(err) {
// 这里接收到了上一个promise传递过来的错误对象
console.log(err); // ReferenceError: a is not defined
})
使用promise/then
进行异步编程时,内部发生的错误不会被外界捕获。但我们可以通过then()
的第二个回调函数参数来获取上一个Promise
实例传递过来的错误。
需要注意的是:错误会沿着then()
方法链一直传递下去,为了简便起见,我们可以在then()
方法链的结尾部署一个 Promise.prototype.catch() 方法统一处理整个流程中发生的错误。
示例:
Promise.resolve()
.then(() => {
// ...
})
.then(() => {
// ...
})
.then(() => {
// ...
})
.catch(err => {
// 捕获整个流程中出现的错误
})