兼容IE大佬的異步流程控制大法

其實工作中一直都有異步流程控制的需求,主要是各種需要順序執(zhí)行的AJAX。

之前請求不多的時候,我就直接簡單粗暴地在回調(diào)里調(diào)用下一個請求函數(shù),隨著項目越來越大,越來越復(fù)雜,這種方式難以維護的缺點就越發(fā)的明顯。大熱的ES6中的promise方法的確很強,然而,需要兼容IE7(現(xiàn)在是IE10了)的我流下了兩行清淚....而且我們項目還未引入打包和配置工具(沒錯就是這么落后),所以沒有辦法愉快地使用Promise等ES6語法和對象。

這個問題一直非常困擾我,想了很久都沒有比較好的解決辦法,直到有一天,看到了一個CSS3動畫的制作,依賴JQ,控制異步動畫的時候完全使用了deferred對象,仿佛打開了異步流程新世界的大門

deferred對象的使用方法

  1. 創(chuàng)建Deferred對象
  2. 在異步流程結(jié)束后改變deferred對象狀態(tài)
  3. 返回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次。

image.png

于是,我做了如下改寫,使用變量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次“我要吃飯啦”,隨后運行“我吃飽啦”

image.png

成功啦~給自己一朵小紅花!

兼容性測試

最后的最后,在IE的各個環(huán)境下進行測試,居然在IE5下也能跑。所以只要是能支持JQ的Deferred對象,一般情況下這種異步流程操作方式都是可行的。

ps:感覺自己是走了歪門邪道,不知道deferred對象中是不是有類似于promise對象中的all可以直接控制多個異步,如果有的話,還希望各位大大能指點迷津

pss:關(guān)于公司還是使用非常傳統(tǒng)開發(fā)方式的問題,只能說上有政策的阻礙,下有業(yè)務(wù)的局限。原因很復(fù)雜,一時半會兒也說不清,所以只能找機會跑路啦哈哈哈哈

學(xué)習(xí)資料:
jQuery的deferred對象詳解——阮一峰

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容