Search code examples
javascriptunderscore.jsmemoizationthrottling

Returning the last computed result in a throttled function


I am working on a exercise based of the underscore _.throttle function. Our function is slightly modified as we have the return the last computed result if the _.throttle function is still waiting to execute the next call. I've managed to make the throttle functionality work, however computing the last result hasn't been successful for me.

What I've tried

I've worked on a memoization function before the throttle function, and I thought that it would be a smart idea to combine both. I've tried multiple different ways of implementing the memoization code in the _.throttle function, but my tests keep failing. Here are 2 of my attempts:

_.throttle = function (func, wait) {
  let throttle = false;
  let cache = {};

  return function (...arguments) {
    const key = JSON.stringify(arguments);
    let result = func.apply(this, arguments);
    cache[key] = result;

    if (!throttle) {
      throttle = true;

      setTimeout(function () {
        throttle = false;
      }, wait);

      return result;
    } else {
      return cache[key];
    }
  };
};
_.throttle = function (func, wait) {
  let throttle = false;
  let cache = {};

  return function (...arguments) {
    const key = JSON.stringify(arguments);

    if (throttle) {
      return cache[key];
    }

    let result = func.apply(this, arguments);
    cache[key] = result;
    throttle = true;

    console.log(cache[key]);


    setTimeout(function () {
      throttle = false;
    }, wait);

    return result;
  };
};

What I am looking for

Basically, I want to return the last computed result if the setTimeout hasn't finished yet. The function that is passed through the _.throttle reverses a string that is passed through its arguments. I have tried several variations of the above code to find out if the return cache[key] is not in the wrong spot and therefore getting the wrong value, but I can't find a location where it works. What am I doing wrong?

Thanks in advance!


Solution

  • Found a way to do exactly what I wanted, without memoization. Turns out you only need to initialise the result before, then save result. Here is the code how I managed to pass my tests:

    _.throttle = function (func, wait) {
      let throttle = false;
      let result;
    
      return function (...arguments) {
        if (throttle) {
          return result;
        }
    
        result = func.apply(this, arguments);
        throttle = true;
    
        setTimeout(function () {
          throttle = false;
        }, wait);
    
        return result;
      };
    };
    

    The above program returns a throttled function. When there are many subsequent calls, the calls will simply return the last computed result! This optimizes the speed of your program.