JS Promise实例 then()方法

描述:

then()方法是Promise标准中最重要的一个部分。

then()方法通过传入的回调函数接收当前Promise实例状态改变时传出的值。

then()方法返回一个新的Promise实例。同时传入的回调函数(参数)的返回值将作为这个promise实例状态改变时传出的值

语法:

Promise.prototype.then(onFulfilled, onRejected);

参数:

参数 描述
onFulfilled 当前Promise实例变成fulfilled状态时调用的回调函数。该函数将接收一个参数,参数值由Promise实例内部的resolve()方法传出。
onRejected 当前Promise实例变成reject状态时调用的回调函数。该函数将接收一个参数,参数值由Promise实例内部的reject()方法传出。

返回值:

then()方法一个新的Promise实例。

简单的then()方法使用示例

/*
* 模拟抛硬币的小游戏:
* 生成一个随机数(值范围0-1),大于0.5表示正面,否则表示反面,硬币在抛出后第二秒静止
 */
function coinFlips(){
    return new Promise((resolve, reject) => {
            setTimeout(() => {
                let n = Math.random();
                    
                n > 0.5 ? resolve(n) : reject(n);
            }, 2000);
        })
}

coinFlips()
.then(value => {
    /*
    * 当Promise实例状态变为fullfilled,将执行此回调函数
    * Promise内部的resolve(n)传入的值n将被这里的value接收
     */
    alert(`硬币是正面,随机值等于:${value}`);
	
},value => {
    /*
    * 当Promise状态变为reject,将执行此回调函数
    * Promise内部的reject()传入的的值n将被这里的value接收
     */
    alert(`硬币是反面,随机值等于:${value}`);
})


// 2秒后弹框输出:硬币是反面,随机值等于:0.4772912322303837

then()方法如何向后传值

为简便起见,以下实例直接使用类似Promise.resolve()来创建Promise实例。

then()方法向后传值分两种情况:

1. 回调函数参数返回一个非Promise实例的值,该值将直接被后续的类then()方法接收。

// 创建一个状态为fullfilled的Promise实例
Promise.resolve('ecmaer')
.then(value => {
	console.info(value); // "ecmaer"
	return String.prototype.toUpperCase.call(value);
})
.then(value => {
	console.info(value); // "ECMAER"
})

2. 回调函数参数返回一个Promise实例的值,后续的类then()方法接收到的值则取决于该promise实例的状态变化。

const p1 = Promise.resolve('success!'),
    p2 = Promise.reject('failed!');

p1
.then(value => {
	console.info(value); // "success!"
	return p2;
})
.then(value => {
	console.info(value);
},value => {
	console.info(value); // "failed!"
});

上面的例子中,第一个then()的回调函数参数返回了promise实例p2,所以第二个then()执行哪个回调函数参数取决于p2的状态。

传入then()的回调函数参数执行报错时,返回的Promise实例状态将变成reject

Promise.resolve()
.then(() => {
    // 这里写一段错误的代码:打印一个未定义的变量
    console.log(a);
})
.then(() => {
    //上面的代码发生错误,所以不会执行这里的代码
}, err => {
	// 这里接收到了上一个promise传递过来的错误对象
    console.log(err); // ReferenceError: a is not defined
})

使用promise/then进行异步编程时,内部发生的错误不会被外界捕获。但我们可以通过then()的第二个回调函数参数来获取上一个promise传递过来的错误。

这里还需要注意的一点是:错误会沿着then()方法链一直传递下去,因此为了简便起见,我们可以在then()方法链的结尾部署一个catch()方法统一处理整个流程中发生的错误。

比如:

Promise.resolve()
.then(() => {
    // ...
})
.then(() => {
    // ...
})
.then(() => {
	// ...
})
.catch(err => {
	// 捕获整个流程中出现的错误
})

控制then()方法返回的Promise实例的状态

默认情况下,只有内部逻辑发生错误时,then()方法才会返回一个reject状态的Promise实例。

但有时候,我们需要手动地让then()返回一个reject状态的Promise实例,我们可以利用Promise.reject()来实现

Promise.resolve()
.then(() => {
    console.log('执行第一个then方法');
})
.then(() => {
	console.log('执行第二个then方法');
    // 使返回的Promise实例变成reject状态
    return Promise.reject();
})
.then(() => {
	// ...
	console.log('执行第三个then方法');
})
.catch(err => {
	console.log('执行catch方法');
})


/* 输出结果:
* 执行第一个then方法
* 执行第二个then方法
* 执行catch方法
*/

相关链接: