Last active
July 20, 2023 16:29
-
-
Save rendall/79a8559ad1b5a022a7923f160f7c429b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Creates a debounced function that delays invoking the provided | |
* function until after `wait` milliseconds have elapsed since the | |
* last time the debounced function was invoked. Typically used to | |
* run an expensive or async function after user interaction. | |
* | |
* @template T The type of the function to debounce. | |
* @param {T} func The function to debounce. | |
* @param {number} [wait=250] The number of milliseconds to delay. | |
* @returns {(...args: Parameters<T>) => void} Returns the new debounced function. | |
* | |
* @example | |
* // Usage with a function that takes one string parameter | |
* const logMessage = (message: string) => console.log(message); | |
* const debouncedLogMessage = debounceFunc(logMessage, 300); | |
* debouncedLogMessage('Hello, world!'); | |
*/ | |
export const debounceFunc = <T extends (...args: unknown[]) => unknown>( | |
func: T, | |
wait = 250 | |
) => { | |
let debounceTimeout: number | null = null | |
return (...args: Parameters<T>): void => { | |
if (debounceTimeout) { | |
window.clearTimeout(debounceTimeout) | |
} | |
debounceTimeout = window.setTimeout(() => { | |
func(...args) | |
}, wait) | |
} | |
} | |
/* | |
// JavaScript | |
var debounceFunc = function (func, wait) { | |
if (wait === void 0) { wait = 250; } | |
var debounceTimeout = null; | |
return function () { | |
var args = []; | |
for (var _i = 0; _i < arguments.length; _i++) { | |
args[_i] = arguments[_i]; | |
} | |
if (debounceTimeout) { | |
window.clearTimeout(debounceTimeout); | |
} | |
debounceTimeout = window.setTimeout(function () { | |
func.apply(void 0, args); | |
}, wait); | |
}; | |
}; | |
// Use | |
const debounceQuery = debounceFunc(sendQuery, 250); | |
// <input onchange=debounceQuery /> | |
// Tests: | |
describe("debounce", () => { | |
it("calls as expected", function (done) { | |
const callingArgument = "debounce it!" | |
const debounceCallback = (value: string) => { | |
expect(value).toBe(callingArgument) | |
done() | |
} | |
const debounce = debounceFunc(debounceCallback) | |
debounce(callingArgument) | |
}) | |
it("does not call immediately", function (done) { | |
const startTime = new Date() | |
const debounceCallback = () => { | |
const duration = new Date().valueOf() - startTime.valueOf() | |
expect(duration).toBeGreaterThan(200) | |
done() | |
} | |
const debounce = debounceFunc(debounceCallback) | |
debounce("") | |
}) | |
it("never calls callback if continuously called", function (done) { | |
let numCalls = 0 | |
const debounceCallback = () => { | |
numCalls++ | |
} | |
const debounce = debounceFunc(debounceCallback) | |
const testInterval = window.setInterval(() => debounce(""), 50) | |
const endTest = (toclear: number) => () => { | |
clearInterval(toclear) | |
expect(numCalls).toBe(0) | |
done() | |
} | |
setTimeout(endTest(testInterval), 500) | |
}) | |
it("calls after its wait time", function (done) { | |
const waitTime = 1000 | |
const startTime = new Date().valueOf() | |
expect.assertions(1) | |
const debounceCallback = () => { | |
const callTime = new Date().valueOf() | |
expect(callTime - startTime).toBeGreaterThanOrEqual(waitTime) | |
done() | |
} | |
const debounce = debounceFunc(debounceCallback, waitTime) | |
debounce("") | |
}) | |
it("calls once only after debounce ends", function (done) { | |
let numCalls = 0 | |
const debounceCallback = () => { | |
numCalls++ | |
} | |
const debounce = debounceFunc(debounceCallback) | |
const testInterval = window.setInterval(() => debounce(""), 50) | |
const endInterval = (toclear: number) => () => { | |
clearInterval(toclear) | |
} | |
const endTest = () => { | |
expect(numCalls).toBe(1) | |
done() | |
} | |
setTimeout(endInterval(testInterval), 200) | |
setTimeout(endTest, 500) | |
}) | |
}) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment