Last active
March 4, 2023 18:39
-
-
Save adnanalbeda/55ba6d0995de21cc115da0ade3aa6be3 to your computer and use it in GitHub Desktop.
Vanilla TS Utils
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
// limit execution of a function to one per x amount of time to the last interaction. | |
// Set 'immediate' to true to run the function then it waits for x time of no interaction. | |
// Keep it undefined or false for default behavior, which is to execute after x time no interaction. | |
export default function debounce( | |
func: () => void, | |
wait: number, | |
immediate?: boolean | |
) { | |
// 'private' variable for instance | |
// The returned function will be able to reference this due to closure. | |
// Each call to the returned function will share this common timer. | |
let timeout: number | null; | |
// Calling debounce returns a new anonymous function | |
return function () { | |
// reference the context and args for the setTimeout function | |
const context = this, | |
args = arguments; | |
// Should the function be called now? If immediate is true | |
// and not already in a timeout then the answer is: Yes | |
const callNow = immediate && !timeout; | |
// This is the basic debounce behavior where you can call this | |
// function several times, but it will only execute once | |
// (before or after imposing a delay). | |
// Each time the returned function is called, the timer starts over. | |
if (timeout != null) clearTimeout(timeout); | |
// Set the new timeout | |
timeout = setTimeout(function () { | |
// Inside the timeout function, clear the timeout variable | |
// which will let the next execution run when in 'immediate' mode | |
timeout = null; | |
// Check if the function already ran with the immediate flag | |
if (!immediate) { | |
// Call the original function with apply | |
// apply lets you define the 'this' object as well as the arguments | |
// (both captured before setTimeout) | |
func.apply(context, args); | |
} | |
}, wait); | |
// Immediate mode and no wait timer? Execute the function... | |
if (callNow) func.apply(context, args); | |
}; | |
} |
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
type DeferredAsync = { | |
promise: Promise<unknown> | null; | |
cancel: (reason?: unknown) => void; | |
}; | |
export function deferredAsync(ms: number): DeferredAsync { | |
let timeout, | |
cancel, | |
promise = new Promise((resolve, reject) => { | |
timeout = setTimeout(resolve, ms); | |
cancel = (reason?: any) => { | |
reject(reason ?? "CANCELED"); | |
clearTimeout(timeout); | |
}; | |
}); | |
return { promise, cancel }; | |
} | |
export function debounceAsync<TParam>(task: (params: TParam) => Promise<unknown>, ms: number) { | |
let t: DeferredAsync = { promise: null, cancel: () => void 0 }; | |
return async (params: TParam) => { | |
try { | |
t.cancel(); | |
t = deferredAsync(ms); | |
await t.promise; | |
await task(params); | |
} catch (_) { | |
/* prevent memory leak */ | |
} | |
}; | |
} |
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
// this function limit execution of a function to one per x amount of time | |
export function throttle(func: () => void, wait: number) { | |
// 'private' variable for instance | |
// The returned function will be able to reference this due to closure. | |
// Each call to the returned function will share this common timer. | |
let timeout: number | null = null; | |
// Calling debounce returns a new anonymous function | |
return function () { | |
// reference the context and args for the setTimeout function | |
const context = this, | |
args = arguments; | |
if (!timeout) { | |
// No timeout means you must execute the function... | |
func.apply(context, args); | |
timeout = setTimeout(function () { | |
// Inside the timeout function, clear the timeout variable | |
// which will let allow fpr the next execution to run | |
timeout = null; | |
}, wait); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment