其實工作中一直都有異步流程控制的需求,主要是各種需要順序執(zhí)行的AJAX。
之前請求不多的時候,我就直接簡單粗暴地在回調(diào)里調(diào)用下一個請求函數(shù),隨著項目越來越大,越來越復(fù)雜,這種方式難以維護的缺點就越發(fā)的明顯。大熱的ES6中的promise方法的確很強,然而,需要兼容IE7(現(xiàn)在是IE10了)的我流下了兩行清淚....而且我們項目還未引入打包和配置工具(沒錯就是這么落后),所以沒有辦法愉快地使用Promise等ES6語法和對象。
這個問題一直非常困擾我,想了很久都沒有比較好的解決辦法,直到有一天,看到了一個CSS3動畫的制作,依賴JQ,控制異步動畫的時候完全使用了deferred對象,仿佛打開了異步流程新世界的大門
deferred對象的使用方法
- 創(chuàng)建Deferred對象
- 在異步流程結(jié)束后改變deferred對象狀態(tài)
- 返回deferred對象
function F(){
var def = $.Deferred(); //創(chuàng)建deferred對象
setTimeout(function(){
console.log("hi~");
def.resolve(); //改變deferred對象狀態(tài)為“已完成”
},50);
return def; //返回deferred對象
}
然后在需要的地方調(diào)用這個異步函數(shù),使用then表示該方法執(zhí)行完后再執(zhí)行下一步
F().then(function(){
//do something you want
});
恩,媽媽再也不用擔(dān)心我的異步了,即便是有多個異步回調(diào)需要控制,也能使用連續(xù)的then寫出漂亮的順序流
F1().then(function(){
F2();
}).then(function(){
F3();
});
似乎回調(diào)依賴的問題已經(jīng)解決了,直到有一天,我遇到了一個循環(huán)異步回調(diào)
一個流程依賴多個異步回調(diào)
大致需求是,有一個循環(huán)體,里面的循環(huán)內(nèi)容是異步流程,大概可以寫成這樣
for(var i = 0 ;i < 10 ; i++){
setTimeout(function(){
console.log("我要吃飯啦~"+i);
});
}
console.log("我吃飽啦~")
promise對象里有個all,可以用放入數(shù)組的形式控制多個異步依賴,沒有編譯工具又要保證兼容性的我再次留下兩行清淚。。研究了半天,好像沒有在Deferred對象中發(fā)現(xiàn)有類似的方法。
于是先是嘗試著,還是使用單個流程控制的方法去寫
function wait(){
var deferred = $.Deferred();
for(var i = 0 ;i < 10 ; i++){
setTimeout(function(){
console.log("我要吃飯啦~"+i);
deferred.resolve();
});
}
return deferred;
}
wait().then(function(){
console.log("我吃飽啦~")
})
emmmmm當(dāng)然這是不對的了,循環(huán)第一次的時候,deferred狀態(tài)就已經(jīng)更改為完成,所以就會執(zhí)行“我吃飽啦”,然后再繼續(xù)執(zhí)行剩余的9次。
于是,我做了如下改寫,使用變量count作為計數(shù)標(biāo)識,當(dāng)計數(shù)循環(huán)完成之后,再改變deferred對象的狀態(tài)。
function wait(){
var dtd = $.Deferred()
var count = 0;
for(var i = 0 ;i < 10 ; i++){
setTimeout(function(){
console.log("我要吃飯啦~"+i);
count++;
if( count == 10 ){
dtd.resolve();
}
},500);
}
return dtd;
}
wait().done(function(){console.log("我吃飽啦")})
運行10次“我要吃飯啦”,隨后運行“我吃飽啦”
成功啦~給自己一朵小紅花!
兼容性測試
最后的最后,在IE的各個環(huán)境下進行測試,居然在IE5下也能跑。所以只要是能支持JQ的Deferred對象,一般情況下這種異步流程操作方式都是可行的。
ps:感覺自己是走了歪門邪道,不知道deferred對象中是不是有類似于promise對象中的all可以直接控制多個異步,如果有的話,還希望各位大大能指點迷津
pss:關(guān)于公司還是使用非常傳統(tǒng)開發(fā)方式的問題,只能說上有政策的阻礙,下有業(yè)務(wù)的局限。原因很復(fù)雜,一時半會兒也說不清,所以只能找機會跑路啦哈哈哈哈
學(xué)習(xí)資料:
jQuery的deferred對象詳解——阮一峰