Skip to content

Instantly share code, notes, and snippets.

@hrishikeshs
Created June 16, 2023 05:20
Show Gist options
  • Save hrishikeshs/29790285797def367ece0d573921940a to your computer and use it in GitHub Desktop.
Save hrishikeshs/29790285797def367ece0d573921940a to your computer and use it in GitHub Desktop.
debounce and throttle implementations in plain english
/**
* It has somehow become very fashionable to ask candidates in frontend engineering interviews
* to implement lodash's _.debounce and _.throttle functions. Though the actual functions
* in both underscore and lodash took days to define, and refine, and the developers
* who implemented them were probably not under a 40 minute time limit.
*
* I have struggled with this myself when I interviewed at a few places last year. My
* approach towards preparing for these questions was to dive into the source code of
* lodash and underscore and understand what the functions were doing. Unfortunately,
* the source code for these functions is pretty complex (and the variable names are hard for me to follow,
* they reference other functions, and they have a bunch of options all of which are not strictly
* necessary for the core functionality), and even after spending time understanding what the code is doing,
* I wasn't able to re-implement it in my interviews in 40 minutes, and I suspect
* it's probably the case for most interviewees. This is my attempt to provide everyone
* an extremely simple code for debounce - simple enough for the readers to understand, and
* implement themselves.
*
* Whether or not this is a good question to gauge if someone is a good FE engineer is a whole
* another question which I won't get into here.
*
* This is my attempt at deriving the implementations of both `debounce` and `throttle` functions from their
* text description so that I never have to think about it again.
*/
/**
* Problem: Debouncing a function means, ensuring that a sequence of calls to that function within a small amount of time,
* only lead to the function execution 1 time. Debouncing is the process of ensuring a series of consecutive function
* calls, lead only to an actual, single function invokation. Given this problem description, let's derive the implementation
* of the `debounce` function.
*/
// takes as it's argument the function that needs to be debounced, like a scroll handler.
// this function should return a function (let's call it A) , which will only call the original
// `functionThatNeedsToBeDebounced` once, no matter how many times A is called by callers within the debounce interval.
const INTERVAL = 5000;
function debounce(functionThatNeedsToBeDebounced) {
let timerId;
return function() {
if (timerId !== undefined) {
// this means this function was invoked before and
// we're still waiting for the original interval to get over.
clearTimeout(timerId);
}
timerId = setTimeout(() => {
timerId = undefined;
functionThatNeedsToBeDebounced.apply(this, arguments);
}, INTERVAL);
}
}
// Now lets test this here:
// helper function to aid us in testing
function now() {
return new Date().getTime();
};
const debouncedConsoleLog = debounce(console.log.bind(console));
for(let i = 0; i < 5; i++) {
console.log("Time before calling is: " , now());
debouncedConsoleLog("Hello, world");
}
// let's call it less frequently here.
setTimeout(() => {
console.log("Time before calling the second time is: " , now());
debouncedConsoleLog("Hello, world2");
}, 6000);
/**
* You can run the above function in jsfiddle and it works as expected. Of course,
* it doesn't take any options such as "WAIT" or "immediate" which modifies the debounce behavior, but
* those would be trivial to add to the above code.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment