2013-02-08 86 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