说明请看注释
/**
* then()方法会返回一个新Promise对象,
* 所以then后面可以继续跟一个then方法进行链式调用,
* 如果then方法的回调函数有返回数据,
* 那么这个数据会作为下一个then的回调函数的参数,
* 如果不需要返回数据,则return可不写
*/
{
let p = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'success');
});
p.then(res => {
console.log(res);
return `${res} again`;
}).then(res => console.log(res));
}
/**
* 结果为:
* success
* success again
*/
/**
* 但是then的回调函数也可能会返回一个Promise对象,
* 这个时候就会覆盖then自己返回的Promise对象(懂原理的人其实发现了,这个理解是错的,但是比较具象,而且这样理解对最终结果没有影响),
* 而且return是必须的
*/
{
let p = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'success');
});
p.then(res => {
console.log(res);
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'success');
});
}).then(res => console.log(res));
}
/**
* 结果为:
* success
* success
*/
以下是一个更复杂的写法,我们按照做饭——吃饭——洗碗的步骤,看看怎么使用链式调用
//做饭
function cook(){
console.log('开始做饭。');
var p = new Promise(function(resolve, reject){ //做一些异步操作
setTimeout(function(){
console.log('做饭完毕!');
resolve('鸡蛋炒饭');
}, 1000);
});
return p;
}
//吃饭
function eat(data){
console.log('开始吃饭:' + data);
var p = new Promise(function(resolve, reject){ //做一些异步操作
setTimeout(function(){
console.log('吃饭完毕!');
resolve('一只碗和一双筷子');
}, 1000);
});
return p;
}
// 洗碗
function wash(data){
console.log('开始洗碗:' + data);
var p = new Promise(function(resolve, reject){ //做一些异步操作
setTimeout(function(){
console.log('洗碗完毕!');
resolve('干净的碗筷');
}, 1000);
});
return p;
}
// 链式调用
cook().then(function(data){
return eat(data); // 返回一个Promise实例
}).then(function(data){
return wash(data); // 返回一个Promise实例
}).then(function(data){
console.log(data);
});
// 链式调用简化写法
cook()
.then(eat)
.then(wash)
.then(function(data){
console.log(data);
});
注意:then可以有两个回调函数作为参数,第一个是当promise状态为解决时的回调,第二个是promise的状态为失败时的回调。
如果发生异常,则会进入catch中,避免js卡死
如果promise发生异常,则会进到then第二个参数的回调函数,如果这个参数不存在,则进到catch中
let p = new Promise((resolve, reject) => {
throw new Error('some errors')
// resolve()
// reject()
});
p.then(res => {
console.log('1111')
},res => {
console.log('2222')
}).catch(e => {
console.log('3333')
})
/**
* 结果为:
* 2222
*/
超级简单!