ES6之Promise的链式调用
我们使用 Promise 的时候,会不断进行后续处理。也就是不断使用 then 方法。有没有一种解决方法可以不去出现回调地狱的问题。我们要先了解 Promise 的链式调用。
按照我的理解,链式调用讲的是首先是将后续结果分为 resolve 和 reject 两种。如果出现没有后续处理的情况,就直接使用前面 Promise 的状态和返回结果。例如:
const p1=new Promise((resolve,reject)=>{
reject(1)
})
const p2=p1.then(data=>{
console.log(data);
})
console.log(p2);
这时输出 p2 , p2 处理的是 p1 成功的结果,而 p1 返回的是失败的结果。p2 就会直接继承 p1 的 reject 和 1 ,这时还处在原来的状态中,没有发生改变。
如果有后续处理情况,但 p1 处于未决阶段,p2 无法执行,p2 只能选择 pending 状态。也就是说,如果无法确定 p1 处于这两种状态,那么只能处于混沌状态,也就是 pending 状态。例如:
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 2000);
})
const p2=p1.then(data=>{
console.log(data);
})
console.log(p2);
像这种情况,p2 在执行的时候 p1 挂起,p2 找不到状态,只能挂起。
如果有后续处理情况,p1 也没有挂起,要看 p2 处理过程中有没有出现报错。如果有报错就会成为 reject 状态,如果成功执行就会成为 resolve 状态。例如:
const p1=new Promise((resolve,reject)=>{
resolve(1)
})
const p2=p1.then(data=>{
console.log(data);
})
console.log(p2);
上面就是成功执行没有报错的情况。如果返回的是一个 Promise 对象,则这个返回对象的结果也是整个 Promise 的结果。
这种情况就是会改变方向的情况。如果发生报错,就来到 reject 状态,如果没有问题,就继续 resolve 状态或者改变原来方向来到 resolve 状态。
catch 方法是 then 方法的 reject 状态,如果要处理报错,就可以写成 catch 形式。实际上,我们处理成功就会用 then ,处理失败就会用 catch 。这是之前那个例子的改造:
function sendMessage(name) {
return new Promise((resolve, reject) => {
// 模拟 发送表白短信
console.log(
`邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
);
console.log(`等待${name}回复......`);
// 模拟 女神回复需要一段时间
setTimeout(() => {
// 模拟 有10%的几率成功
if (Math.random() <= 0.3) {
// 成功,调用 onFuffiled,并传递女神的回复
resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
} else {
// 失败,调用 onRejected,并传递女神的回复
reject(`${name} -> 邓哥:你是个好人😜`);
}
}, 1000);
});
}
sendMessage('小明')
.catch(reply=>{
console.log(reply);
return sendMessage('小张')
})
.catch(reply=>{
console.log(reply);
return sendMessage('小王')
})
.catch(reply=>{
console.log(reply);
return sendMessage('小李')
})
.then(
(reply) => {
// 成功,结束
console.log(reply);
console.log('邓哥终于找到了自己的伴侣');
},
(reply) => {
// 最后一个也失败了
console.log(reply);
console.log('邓哥命犯天煞孤星,无伴终老,孤独一生');
}
);
通过 catch 方法,把每个失败的过程进行切割,同时返回一个 Promise ,可以有效地处理回调地狱的问题。