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 => {
    // 捕获整个流程中出现的错误
})

相关链接: