Skip to content

Instantly share code, notes, and snippets.

@beaucharman
Last active November 12, 2022 15:39
Show Gist options
  • Save beaucharman/e46b8e4d03ef30480d7f4db5a78498ca to your computer and use it in GitHub Desktop.
Save beaucharman/e46b8e4d03ef30480d7f4db5a78498ca to your computer and use it in GitHub Desktop.
An ES6 implementation of the throttle function. "Throttling enforces a maximum number of times a function can be called over time. As in 'execute this function at most once every 100 milliseconds.'" - CSS-Tricks (https://css-tricks.com/the-difference-between-throttling-and-debouncing/)
function throttle(callback, wait, immediate = false) {
let timeout = null
let initialCall = true
return function() {
const callNow = immediate && initialCall
const next = () => {
callback.apply(this, arguments)
timeout = null
}
if (callNow) {
initialCall = false
next()
}
if (!timeout) {
timeout = setTimeout(next, wait)
}
}
}
/**
* Normal event
* event | | |
* time ----------------
* callback | | |
*
* Call search at most once per 300ms while keydown
* keydown | | | |
* time -----------------
* search | |
* |300| |300|
*/
const input = document.getElementById('id')
const handleKeydown = throttle((arg, event) => {
console.log(`${event.type} for ${arg} has the value of: ${event.target.value}`)
}, 300)
input.addEventListener('keydown', (event) => {
handleKeydown('input', event)
})
@benneq
Copy link

benneq commented Nov 12, 2022

Here's my version, using TypeScript. It's returning a callback to cancel the timeout, useful if use have to use some cleanup function.

const throttle = <TArgs extends unknown[] = []>(
  callback: (...args: TArgs) => void
): ((ms: number, ...args: TArgs) => (() => void)) => {
  let timeout: NodeJS.Timeout | undefined;
  let lastArgs: TArgs;

  const cancel = () => {
    clearTimeout(timeout);
  };

  return (ms, ...args) => {
    lastArgs = args;

    if (!timeout) {
      timeout = setTimeout(() => {
        callback(...lastArgs);
        timeout = undefined;
      }, ms);
    }

    return cancel;
  };
};

Usage:

const cb = (n) => console.log(n);
const throttledCb = throttle(cb);
throttledCb(100, 1);
// wait 50ms
throttledCb(100, 2);
// wait 50ms
// prints 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment