javascript的閉包與一次重構的感覺

 

  有沒有這麼一個場景,你的一個動做須要在全部異步方法執行完畢後,再進行操做?然而你對異步方法什麼時候執行完畢感到困擾,只能在每一個方法中寫回調,在回調中重複勞動?數組

  偶然的,想起了以前經理講過的閉包的概念,偶然的,以爲能夠應用到代碼中。閉包

  例如在某個動做的時候須要觸發三個異步方法,他們爲a(),b(),c()。咱們在d()方法中執行a,b,c。而後在三個方法執行後須要拋出一個動做,然而咱們怎麼知道這三個異步方法何時執行完呢?而且準確的在執行完的最後那個方法後拋出這個動做呢?異步

  //異步a
    function a(cb){
        .....
     if(cb)cb(); } //異步b function b(cb){ .....
     if(cb)cb(); } //異步c function c(cb){ .....
    if(cb)cb(); } //動做 function action(){ ... } //調用者 function main(){ a(); b(); c(); action(); }

  本來我是用一個全局變量count記錄執行次數,在每一個方法的回調中將執行次數減去。當有一個回調方法內的count被減爲0的時候,就證實方法都執行完畢了。函數

    var count=3;
    //異步a
    function a(){ ..... if(--count<=0){ action(); } } //異步b function b(){ ..... if(--count<=0){ action(); } } //異步c function c(){ ..... if(--count<=0){ action(); } } //調用者 function main(){ a(); b(); c(); //action(); }

  是的,這個方法是能實現的,可是這個方法有點弊端,首先count是個固定值,你必須事先知道有多少個方法要執行,就是要本身數,若是新加了方法,那還要從新改變count的值,很明顯這和咱們的'開放-關閉'原則是背道而馳的。其次每一個方法都要寫一串相同的代碼,複用性過低,重複性代碼太多。最後,每一個方法都要訪問全局變量,這增長了全局資源,用咱們經理說過的話,就是由於方法內的邏輯污染了到外部或全局代碼。性能

  明白了這樣寫的弊端,天然是要改了。  優化

  《代碼大全》中對'表查詢法'有着很高的評價,即簡潔了代碼,又增長了可讀性,在一些場景中甚至是提升代碼性能的利器,咱們何不利用?spa

initFun:function(){    //初始化           
                var funArr = [a, b, c];                 funArr.forEach(function (item) { item(); }) } 

  好了,接下來如何用閉包實現準確在三個方法執行後調用回調?code

  在這以前,咱們先看看閉包的特性:訪問外部變量,保持外部變量。blog

  訪問外部變量就是能在方法內訪問外部變量,參數,局部變量或函數。保持外部變量是指把訪問的外部變量拘留在這個方法的上下文中,每次調用方法都會帶着這個上下文。簡單來講就是把咱們訪問的這個外部變量存儲在了這個方法的內存中,相似自帶一個全局變量同樣。內存

  那麼咱們該如何應用到代碼中呢?

    //異步a
    function a(cb){
        .....
    if(cb)cb(); } //異步b function b(cb){ .....
    if(cb)cb(); } //異步c function c(){ .....
     if(cb)cb(); }
  ...... //閉包調用 function closureFun(closureCount, closureCb) {var count = closureCount; var callback = closureCb; return function () { if (!--count) { callback(); } } }, //初始化 function initFun(){
     var funArr = [a, b, c]; //執行完全部異步方法後的回調方法 var callBack = function () { console.log('i am callback'); } //註冊閉包代碼 var testClosureFun = me.methods.closureFun(funArr.length, callBack); funArr.forEach(function (item) { item(testClosureFun); }) },

  初始化方法中參照表查詢法,將方法暫留在一個數組中,寫好回調方法,並將其註冊到閉包方法。funArr.length是這個閉包方法訪問的外部變量,是閉包內部判斷後最終將運行的次數,每次運行完一個方法,數量減一,當全部方法執行完畢,count也就爲0了,這時候就會調用回調方法。

  這段代碼沒有污染到全局,方法的數量也自動計算,每一個方法中抽離了重複代碼,也算是優化了點吧。

  雖然這不必定是最好的選擇,但能在偶然間把本身學到的知識應用到實際中,成就感天然也是滿滿的。

  固然這優化手段有什麼缺陷或不足,望能指出,若是有更好的重構方案,有人知道並能指點一二,那也是鄙人的榮幸了。

相關文章
相關標籤/搜索