其實工做中一直都有異步流程控制的需求,主要是各類須要順序執行的AJAX。jquery
以前請求很少的時候,我就直接簡單粗暴地在回調裏調用下一個請求函數,隨着項目愈來愈大,愈來愈複雜,這種方式難以維護的缺點就愈加的明顯。大熱的ES6中的promise方法的確很強,然而,須要兼容IE7(如今是IE10了)的我流下了兩行清淚....並且咱們項目還未引入打包和配置工具(沒錯就是這麼落後),因此沒有辦法愉快地使用Promise等ES6語法和對象。數組
這個問題一直很是困擾我,想了好久都沒有比較好的解決辦法,直到有一天,看到了一個CSS3動畫的製做,依賴JQ,控制異步動畫的時候徹底使用了deferred對象,彷彿打開了異步流程新世界的大門promise
function F(){
var def = $.Deferred(); //建立deferred對象
setTimeout(function(){
console.log("hi~");
def.resolve(); //改變deferred對象狀態爲「已完成」
},50);
return def; //返回deferred對象
}
複製代碼
而後在須要的地方調用這個異步函數,使用then
表示該方法執行完後再執行下一步bash
F().then(function(){
//do something you want
});
複製代碼
恩,媽媽不再用擔憂個人異步了,即使是有多個異步回調須要控制,也能使用連續的then
寫出漂亮的順序流異步
F1().then(function(){
F2();
}).then(function(){
F3();
});
複製代碼
彷佛回調依賴的問題已經解決了,直到有一天,我遇到了一個循環異步回調函數
大體需求是,有一個循環體,裏面的循環內容是異步流程,大概能夠寫成這樣工具
for(var i = 0 ;i < 10 ; i++){
setTimeout(function(){
console.log("我要吃飯啦~"+i);
});
}
console.log("我吃飽啦~")
複製代碼
promise
對象裏有個all
,能夠用放入數組的形式控制多個異步依賴,沒有編譯工具又要保證兼容性的我再次留下兩行清淚。。研究了半天,好像沒有在Deferred對象中發現有相似的方法。學習
因而先是嘗試着,仍是使用單個流程控制的方法去寫測試
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固然這是不對的了,循環第一次的時候,deferred狀態就已經更改成完成,因此就會執行「我吃飽啦」,而後再繼續執行剩餘的9次。動畫
因而,我作了以下改寫,使用變量count做爲計數標識,當計數循環完成以後,再改變deferred對象的狀態。
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的各個環境下進行測試,竟然在IE5下也能跑。因此只要是能支持JQ的Deferred對象,通常狀況下這種異步流程操做方式都是可行的。
ps
:感受本身是走了歪門邪道,不知道deferred
對象中是否是有相似於promise
對象中的all
能夠直接控制多個異步,若是有的話,還但願各位大大能指點迷津
pss
:關於公司仍是使用很是傳統開發方式的問題,只能說上有政策的阻礙,下有業務的侷限。緣由很複雜,一時半會兒也說不清,因此只能找機會跑路啦哈哈哈哈
學習資料: jQuery的deferred對象詳解——阮一峯