2013-02-08 48 views
1

今天我感覺很愚蠢。 我一直在看這段代碼,試圖跟蹤它,但我只是想不通:這個memoize函數是如何工作的?

  1. 什麼它實際上是爲了做
  2. 它是如何工作

至於我可以看到,這是第一次,這是唯一的時間action是相同的callFn。所以,它第一次運行時會創建堆棧數組。然後我失去了它。 Action分配了一個函數,將傳入的回調添加到堆棧。然後fn是實際上調用並根據其結果,「action」被設置爲callFn(?!?)或調用回調函數...然後,調用堆棧中的所有調用。

我討厭在代碼中迷路,但這有點超出我的想象。比我更聰明的人能夠「得到它」嗎?

var memoize = function(fn) { 
    var callFn = function(callback) { 
     var stack = [callback]; 

     action = function(callback) { 
      stack.push(callback); 
     }; 

     fn(function(err, val) { 
      action = err ? callFn : function(callback) { 
       callback(null, val); 
      }; 

      while (stack.length) stack.shift()(err, val); 
     }); 
    }; 

    var action = callFn; 

    return function(callback) { 
     action(callback); 
    }; 
}; 
+0

這有點神祕。這裏的參考是一個更容易閱讀memoize函數形式的版本underscore.js:http://underscorejs.org/docs/underscore.html#section-60 – 2013-02-08 23:14:32

+0

你有一個如何看待它被使用的例子? – 2013-02-08 23:19:25

+0

你從哪裏得到這個功能? – Bergi 2013-02-08 23:21:43

回答

1

它不僅memoize的的fn的結果,這也確保了有一次到fn只有一個活動的呼叫。在活動呼叫期間提供的每個callback(當action是來自第5行的匿名函數)被壓入堆棧,並且一旦fn回調堆棧(實際上是一個隊列)將被處理並且結果被髮布到所有回調。

混亂的「action被設置爲callFn或...」偏偏基礎上,err條件。此參數爲indicates that an error happened,否則爲虛假。所以,當fn調用回一個錯誤,堆棧像往常一樣處理也是action復位原來的callFn(你還記得,它必須在一開始該值也一樣),以便後續調用將重試得到值爲fn。如果沒有錯誤,則action只設置爲一個函數,該函數總是返回一次返回的結果val

+0

Ahhhhhhhhhhhhhhhh這非常有道理!這是一個來自https://github.com/gett/mongojs的函數 - 這是一個常見的模式,與「隊列」等?現在看,它看起來非常聰明,整潔。你不覺得嗎?感謝百萬解釋它... – Merc 2013-02-09 04:05:20

+0

是的,它很聰明。然而我害怕智能不是太常見......大多數庫(mongojs,jQuery.Callback)都有抽象函數,所以你不必自己處理隊列。 – Bergi 2013-02-09 11:59:41

0

memoization的是使用的副作用,改善-at runtime-的函數的性能,而不改變它的行爲的技術。粗略地說,您可以通過存儲先前調用中返回的函數值來進行記憶,並在進一步調用函數時返回這些值,而不是實際調用該函數。

Read more