前言
函數(shù)作為一等對(duì)象,使得javascript這種弱類型,單線程腳本語言的異步方法極為方便,只需要一個(gè)callback兔港,編譯器就能按照我們的想法執(zhí)行命令。如果只有一個(gè)簡單的異步操作仔拟,我們可以稍費(fèi)腦子理清執(zhí)行順序衫樊,但是如果有多個(gè)異步方法,呃,我們就可能掉進(jìn)了回調(diào)陷阱科侈,事情遠(yuǎn)遠(yuǎn)沒有我們想到的那么簡單载佳,并且我們甚至還沒考慮過異步中拋出的錯(cuò)誤。
還好Promise的出現(xiàn)臀栈,解救了我們蔫慧,這篇文章不是講解Promise的詳細(xì)使用方法,只是通過兩個(gè)例子权薯,看看Promise的優(yōu)雅之處姑躲,詳細(xì)資料請參考阮一峰老師 《ES6標(biāo)準(zhǔn)入門》
傳統(tǒng)的ajax回調(diào)
代碼運(yùn)行于最新的Chrome版本中,Chrome目前已支持除 模塊 以外的大部分ES6方法
let xhr = new XMLHttpRequest();
let url = 'http://chat.hstar.org:8601/rkyNA2Yvl/promise';
xhr.responseType = "text";
xhr.open('get', url, true);
xhr.onreadystatechange = ((data) => {
if (xhr.readyState===4 && xhr.status===200) {
let data = JSON.parse(xhr,responseText);
console.log(data.word);
}
});
xhr.send(null);
這是一個(gè)傳統(tǒng)的ajax回調(diào)盟蚣,我們把所有事務(wù)邏輯封裝在
onreadystatechange
事件中黍析,并且xhr的生成與使用都在一塊代碼內(nèi)。后期的維護(hù)屎开、DOM操作都只能該事件中進(jìn)行阐枣,這只是一個(gè)異步事件,如果是多個(gè)異步事件牍戚,并且需要所有事件都能完成才能操作侮繁。Oh my god虑粥。我們可能已經(jīng)進(jìn)入回調(diào)地獄如孝。這團(tuán)代碼在后期debug時(shí)候足以讓我們抓狂。
Promise的出現(xiàn)
我們再來看看一段經(jīng)過Promise封裝的代碼
function getPromise(url) {
let p = new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest;
xhr.open('get', url, true);
xhr.onreadystatechange = () => {
if (xhr.status == 200 && xhr.readyState===4 ){
resolve(xhr.responseText);
}
};
xhr.onerr = function () {
reject();
}
xhr.send(null);
});
return p;
}
首先封裝一個(gè)Promise對(duì)象娩贷,我們把響應(yīng)事件封裝在resolve
方法中第晰,如果僅僅是這樣,那么和普通封裝沒有區(qū)別彬祖,我們接著來看看Promise的優(yōu)雅之處
let promise = getPromise('http://chat.hstar.org:8601/rkyNA2Yvl/promise');
promise.
then(data => {
data = JSON.parse(data);
return data;
}).then(data => {
document.write(data.word);
console.log(data);
}).catch(err => {
console.log(err);
});
我們通過then(resolve方法的別名)茁瘦,進(jìn)行回調(diào)操作,then方法返回的也是一個(gè)Promise對(duì)象储笑,因此可以鏈?zhǔn)秸{(diào)用甜熔,這樣我們可以按步驟操作返回的數(shù)據(jù)。并且catch方法會(huì)捕捉每一個(gè)異步方法中的錯(cuò)誤突倍,所有的錯(cuò)誤都會(huì)冒泡到這里腔稀,如果catch方法出現(xiàn)了錯(cuò)誤怎么辦?別擔(dān)心done()方法會(huì)處理最后的錯(cuò)誤羽历。
通過這樣的鏈?zhǔn)秸{(diào)用焊虏,使得 關(guān)注點(diǎn) 分離,return的形式也更符合人腦的思考邏輯秕磷。
前面還提到了多個(gè)異步操作诵闭,我們同樣可以使用Promise.all和Promise.race方法。
最后
相比傳統(tǒng)的ajax方法,Promise的優(yōu)雅之處在于
- 關(guān)注點(diǎn)分離疏尿,每一次調(diào)用只需要完成一個(gè)任務(wù)瘟芝;
- 更符合人腦思考邏輯;
- 良好的錯(cuò)誤處理邏輯褥琐,錯(cuò)誤冒泡模狭;
- all() 和 race()方法避免陷入回調(diào)地獄
這里僅僅是簡單封裝了XMLHttpRequest方法,隨著JS的發(fā)展踩衩,fetch axios vue-resource等新一代ajax方法都已經(jīng)實(shí)現(xiàn)了對(duì)Promise的封裝嚼鹉,這里也該大家分享一段我們項(xiàng)目對(duì)Promise的深度封裝實(shí)現(xiàn)(基于axios)
所以大家也快來擁抱ES6的新特性吧
就是這樣:)