Skip to content

Instantly share code, notes, and snippets.

@dossy
Last active January 5, 2024 18:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dossy/bfe4277325516a590c2ac5219e072a59 to your computer and use it in GitHub Desktop.
Save dossy/bfe4277325516a590c2ac5219e072a59 to your computer and use it in GitHub Desktop.
Helpful JS utilities
/**
* Sleeps for `ms` milliseconds.
*
* @param {number} ms - Sleep duration in milliseconds.
* @returns {Promise<void>}
*
* @example
* // Sleep for 250ms.
* await sleep(250);
*/
export function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}
/**
* Wait for a condition to be satisfied, or optionally time out.
*
* @param {function()} f - Function to test whether event has occurred or not.
* @param {number} [until=0] - Milliseconds to wait for event, or `0` means indefinitely. [default: 0]
* @param {number} [frequency=200] - How many milliseconds to wait between calls to `f`. [default: 200]
* @returns {*} The most recent return value of the function `f`.
*
* @example
* // Wait for the DOM element with ID `foo` to be found.
* await waitFor(() => document.getElementById('foo'));
*/
export async function waitFor(f, until = 0, frequency = 200) {
let value = undefined,
elapsed = 0;
while (!(value = await f())) {
if (until > 0 && (elapsed += frequency) > until) break;
await sleep(frequency);
}
return value;
}
/**
* Debounce calls to `f`. Only invoke `f` once after `timeout` has elapsed.
*
* @param {function(...)} f - The function to debounce.
* @param {number} [timeout=100] - The number of milliseconds to debounce for. [default: 100]
* @returns {function(...)} The function that debounces calls to `f`.
*
* @example
* // Only invoke the debounced code once after `timeout` milliseconds has passed.
* new MutationObserver(
* debounce(() => {
* // debounced code here
* })
* ).observe(...);
*/
export function debounce(f, timeout = 100) {
var timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
f.apply(this, args);
}, timeout);
};
}
/**
* Throttle calls to `f`. Only invoke `f` once until `timeout` has elapsed.
*
* @param {function(...)} f - The function to throttle.
* @param {number} [timeout=100] - The number of milliseconds to throttle for. [default: 100]
* @returns {function(...)} The function that throttles calls to `f`.
*
* @example
* // Only invoke the throttled code once per every `timeout` milliseconds.
* onClick={
* throttle(
* () => {
* // throttled code here
* }
* }
* }
*/
export function throttle(f, timeout = 100) {
var timer;
return (...args) => {
if (!timer) {
f.apply(this, args);
}
clearTimeout(timer);
timer = setTimeout(() => {
timer = undefined;
}, timeout);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment