異步無處不在:Promise 破除“回調(diào)地獄”(三)
(????)??嗨,我是你穩(wěn)定更新、干貨賊多的勾勾。

前兩篇討論了異步模式和回調(diào)函數(shù),結(jié)尾談到了令人頭皮發(fā)麻的回調(diào)地獄。
要想拯救出回調(diào)地獄的代碼,只有請(qǐng)我們的 Promise 出山了。
拯救頭發(fā)小斗士,出發(fā)!
Promise

Promise 譯為承諾、許諾、希望,意思就是異步任務(wù)交給我來做,一定(承諾、許諾)給你個(gè)結(jié)果。
在執(zhí)行的過程中,Promise 的狀態(tài)會(huì)修改為 pending。一旦有了結(jié)果,就會(huì)再次更改狀態(tài)。
異步執(zhí)行成功的狀態(tài)是 Fulfilled , 這就是承諾給你的結(jié)果。狀態(tài)修改后,會(huì)調(diào)用成功的回調(diào)函數(shù) onFulfilled 來將異步結(jié)果返回。
異步執(zhí)行成功的狀態(tài)是 Rejected,這就是承諾給你的結(jié)果。然后調(diào)用 onRejected 說明失敗的原因(異常接管)。
如果將前面對(duì) ajax 函數(shù)的封裝,改為 Promise ?的方式,結(jié)果又會(huì)是什么?
Promise 重構(gòu) Ajax 的異步請(qǐng)求封裝
function myAjax(url) {return new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (this.readyState == 4) {if (this.status == 200) {// 成功的回調(diào)resolve(this.responseText)} else {// 失敗的回調(diào)reject(new Error());}}}xhr.open('get', url)xhr.send();})}
還是前面提到的邏輯,如果返回的結(jié)果中,又有 ajax 請(qǐng)求需要發(fā)送,可一定記得使用鏈?zhǔn)秸{(diào)用,不要在 then 中直接發(fā)起下一次請(qǐng)求,否則,又是地獄相見了。
// ==== Promise 誤區(qū)====myAjax('./d1.json').then(data=>{console.log(data);myAjax('./d2.json').then(data=>{console.log(data)// ……回調(diào)地獄……})})
鏈?zhǔn)降囊馑季褪窃谏弦淮?then 中,返回下一次調(diào)用的 Promise 對(duì)象,我們的代碼就不會(huì)進(jìn)地獄了。
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);})
終于逃脫了回調(diào)地獄!
雖然我們脫離了回調(diào)地獄,但是 .then 的鏈?zhǔn)秸{(diào)用依然不太友好。
頻繁的 .then 并不符合自然的運(yùn)行邏輯,Promise 的寫法只是回調(diào)函數(shù)的改進(jìn),使用then 方法以后,異步任務(wù)的兩段執(zhí)行看得更清楚了,除此以外,并無新意。
Promise 的最大問題是代碼冗余。原來的任務(wù)被 Promise 包裝了一下,不管什么操作,一眼看去都是一堆 then,原來的語義變得很不清楚。
于是,在 Promise 的基礎(chǔ)上,Async 函數(shù)出現(xiàn)了。
終極異步解決方案,千呼萬喚地在 ES2017 中發(fā)布了。
下一篇,展開說說(? ?_?)?。
推薦閱讀:
技術(shù)人年度總結(jié) | 2020,注定不平凡
前端人因?yàn)?Vue3 的 Ref-sugar 提案打起來了!
點(diǎn)點(diǎn)“贊”和“在看”,保護(hù)頭發(fā),減少bug。
