异步无处不在:Promise 破除“回调地狱”(三)
共 2025字,需浏览 5分钟
·
2021-01-13 14:14
(。・∀・)ノ゙嗨,我是你稳定更新、干货贼多的勾勾。
前两篇讨论了异步模式和回调函数,结尾谈到了令人头皮发麻的回调地狱。
要想拯救出回调地狱的代码,只有请我们的 Promise 出山了。
拯救头发小斗士,出发!
Promise
Promise 译为承诺、许诺、希望,意思就是异步任务交给我来做,一定(承诺、许诺)给你个结果。
在执行的过程中,Promise 的状态会修改为 pending。一旦有了结果,就会再次更改状态。
异步执行成功的状态是 Fulfilled , 这就是承诺给你的结果。状态修改后,会调用成功的回调函数 onFulfilled 来将异步结果返回。
异步执行成功的状态是 Rejected,这就是承诺给你的结果。然后调用 onRejected 说明失败的原因(异常接管)。
如果将前面对 ajax 函数的封装,改为 Promise 的方式,结果又会是什么?
Promise 重构 Ajax 的异步请求封装
function myAjax(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
// 成功的回调
resolve(this.responseText)
} else {
// 失败的回调
reject(new Error());
}
}
}
xhr.open('get', url)
xhr.send();
})
}
还是前面提到的逻辑,如果返回的结果中,又有 ajax 请求需要发送,可一定记得使用链式调用,不要在 then 中直接发起下一次请求,否则,又是地狱相见了。
// ==== Promise 误区====
myAjax('./d1.json').then(data=>{
console.log(data);
myAjax('./d2.json').then(data=>{
console.log(data)
// ……回调地狱……
})
})
链式的意思就是在上一次 then 中,返回下一次调用的 Promise 对象,我们的代码就不会进地狱了。
myAjax('./d1.json')
.then(data=>{
console.log(data);
return myAjax('./d2.json')
})
.then(data=>{
console.log(data)
return myAjax('./d3.json')
})
.then(data=>{
console.log(data);
})
.catch(err=>{
console.log(err);
})
终于逃脱了回调地狱!
虽然我们脱离了回调地狱,但是 .then 的链式调用依然不太友好。
频繁的 .then 并不符合自然的运行逻辑,Promise 的写法只是回调函数的改进,使用then 方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。
Promise 的最大问题是代码冗余。原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆 then,原来的语义变得很不清楚。
于是,在 Promise 的基础上,Async 函数出现了。
终极异步解决方案,千呼万唤地在 ES2017 中发布了。
下一篇,展开说说(ง •_•)ง。
推荐阅读:
前端人因为 Vue3 的 Ref-sugar 提案打起来了!
点点“赞”和“在看”,保护头发,减少bug。