Promise開(kāi)篇
因?yàn)閖avascript異步機(jī)制,導(dǎo)致一個(gè)常見(jiàn)的問(wèn)題,回調(diào)金字塔:
loadImg('a.jpg', function() {
loadImg('b.jpg', function() {
loadImg('c.jpg', function() {
console.log('all done!');
});
});
});
Promise 字面意思,承諾。如果A調(diào)用B,B返回一個(gè)承諾給A,然后A就可以寫計(jì)劃時(shí)這么寫:當(dāng)B返回結(jié)果給我的時(shí)候,A執(zhí)行S1方案,反之如果B因?yàn)槭裁丛驔](méi)有給A想要的結(jié)果,那么A執(zhí)行應(yīng)急方案S2,這樣的話,所有潛在風(fēng)險(xiǎn)都在A的控制范圍內(nèi)
var resB = B();
var runA = function(){
resB.then(execS1,execS2);
};
如果A要完成一件事,可能依賴的不是B一個(gè)響應(yīng),那么上面的代碼就會(huì)變成
var resB = B();
var resC = C();
...
var runA = function() {
reqB
.then(resC, execS2)
.then(resD, execS3)
.then(resE, execS4)
...
.then(execS1);
};
runA();
在這里,每當(dāng)一個(gè)詢問(wèn)者做出不符合預(yù)期的應(yīng)答的時(shí)候都用了不同的處理機(jī)制,雖然,Promise規(guī)范沒(méi)有要求這樣做,甚至可以不做任何處理,即(不傳入then的第二個(gè)參數(shù)),或者統(tǒng)一處理
Promise/A+規(guī)范
- 一個(gè)Promise可能存在三種狀態(tài):等待(pending),已完成(fulfilled),已拒絕(rejected)
- 一個(gè)Promise的狀態(tài)只可能從"等待"轉(zhuǎn)到"完成"或者"拒絕",不能逆向轉(zhuǎn)換
- Promise必須實(shí)現(xiàn)then方法,(then是promise核心),而且then必須返回一個(gè)promise,同一個(gè)promise的then可以調(diào)用多次,并且回調(diào)執(zhí)行的順序和它們定義的順序一樣。
- then方法接受兩個(gè)參數(shù),第一個(gè)參數(shù)是成功時(shí)候的回調(diào),另一個(gè)是失敗的回調(diào),then可以接受另一個(gè)promise傳入,也接受一個(gè)"類then"的對(duì)象或者方法,即thenable對(duì)象
標(biāo)準(zhǔn)的Promise
可參考html5rocks的這篇文章JavaScript Promises,目前高級(jí)瀏覽器如chrome、firefox都已經(jīng)內(nèi)置了Promise對(duì)象,提供更多的操作接口,比如Promise.all()
,支持傳入一個(gè)promises數(shù)組,當(dāng)所有promises都完成時(shí)執(zhí)行then,還有就是更加友好強(qiáng)大的異常捕獲,應(yīng)對(duì)日常的異步編程,應(yīng)該足夠了。
第三方庫(kù)的Promise
現(xiàn)今流行的各大js庫(kù),幾乎都不同程度的實(shí)現(xiàn)了Promise,如dojo,jQuery、Zepto、when.js、Q等,只是暴露出來(lái)的大都是Deferred
對(duì)象,
尾聲
我們看到,不管Promise實(shí)現(xiàn)怎么復(fù)雜,但是它的用法卻很簡(jiǎn)單,組織的代碼很清晰,從此不用再受callback的折磨了。
最后,Promise是如此的優(yōu)雅!但Promise也只是解決了回調(diào)的深層嵌套的問(wèn)題,真正簡(jiǎn)化JavaScript異步編程的還是Generator,在Node.js端,建議考慮Generator。