Reputation: 17067
I am feeling very stupid today. I keep looking at this code, trying to trace it, but I just cannot figure out:
As far as I can see, the very first time it's called it's the only time action
is the same as callFn
. So, the very first time it's run, it creates the stack array. Then I lose it. Action is assigned a function that just adds the passed callback to the stack. Then fn is actually called and based on its result, "action" is set to either callFn (?!?) or to a function that calls the callback... And then, all the calls in the stack are called.
I hate getting lost in code, but this is a little beyond me. Anybody smarter than me able to "get it"?
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);
};
};
Upvotes: 1
Views: 909
Reputation: 664484
It does not only memoize the result of fn
, it also ensured that there is only one active call to fn
at a time. Every callback
that is provided during an active call (when action
is that anon function from line 5) is pushed on the stack, and once fn
calls back the stack (it's a queue actually) is processed and the result is published to all callbacks.
The confusing "action
is set to either callFn
or…" happens based on the err
condition. This parameter indicates that an error happened and is falsy otherwise. So when fn
calls back with an error, the stack is processed as usual but also the action
is reset to the original callFn
(you remember, it had that value at the beginning as well) so subsequent calls will retry to get a value from fn
. If there was no error, the action
is just set to a function that always calls back with the result val
that came back once.
Upvotes: 1
Reputation: 33408
Memoization is a technique that uses side-effects to improve -at runtime- the performance of a function without altering its behavior. Roughly speaking, you can do memoization by storing function values that were returned in previous calls, and returning these values in further calls to the function instead of actually calling the function.
Upvotes: 0