標籤:ack 自己 div 大全 計算 methods 方法 span 全域
我在修改bug的時候,偶然的,想起了之前經理講過的閉包的概念,偶然的,覺得可以應用到代碼中。
有沒有這麼一個情境,你的一個動作需要在所有非同步方法呼叫執行完畢後,再進行操作?然而你對非同步方法呼叫何時執行完畢感到困擾,只能在每個方法中寫回調,在回調中重複勞動?
例如在某個動作的時候需要觸發三個非同步方法呼叫,他們為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是個固定值,你必須事Crowdsourced Security Testing道有多少個方法要執行,就是要自己數,如果新加了方法,那還要重新改變count的值,很明顯這和我們的‘開放-關閉‘原則是背道而馳的。其次每個方法都要寫一串相同的代碼,複用性太低,重複性代碼太多。最後,每個方法都要訪問全域變數,這增加了全域資源,用我們經理說過的話,就是因為方法內的邏輯汙染了到外部或全域代碼。
明白了這樣寫的弊端,自然是要改了。
《代碼大全》中對‘表查詢法‘有著很高的評價,即簡潔了代碼,又增加了可讀性,在一些情境中甚至是提高代碼效能的利器,我們何不利用?
initFun:function(){ //初始化 var funArr = [a, b, c]; funArr.forEach(function (item) { item(); }) }
好了,接下來如何用閉包實現準確在三個方法執行後調用回調?
在這之前,我們先看看閉包的特性:訪問外部變數,保持外部變數。
訪問外部變數就是能在方法內訪問外部變數,參數,局部變數或函數。保持外部變數是指把訪問的外部變數拘留在這個方法的上下文中,每次調用方法都會帶著這個上下文。簡單來說就是把我們訪問的這個外部變數儲存在了這個方法的記憶體中,類似內建一個全域變數一樣。
那麼我們該如何應用到代碼中呢?
//非同步a function a(){ ..... } //非同步b function b(){ ..... } //非同步c function c(){ ..... }
...... //閉包調用 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了,這時候就會調用回調方法。
這段代碼沒有汙染到全域,方法的數量也自動計算,每個方法中抽離了重複代碼,也算是最佳化了點吧。
或許以上還有許多地方可以最佳化,也或許我的最佳化並不是特別好的,有更好的最佳化策略。如果有人知道並能指點一二,那也是鄙人的榮幸了。
前端菜鳥望大神們指點。
關於javascript閉包與重構