Merc
Merc

Reputation: 17067

How does this memoize function work?

I am feeling very stupid today. I keep looking at this code, trying to trace it, but I just cannot figure out:

  1. What it's actually meant to do
  2. How it works

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

Answers (2)

Bergi
Bergi

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

yckart
yckart

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.

Read more

Upvotes: 0

Related Questions