Created
January 11, 2021 09:57
-
-
Save stropitek/a2cf7f311cae4cf863192bcc9fc4c827 to your computer and use it in GitHub Desktop.
Debounce function execution
This file contains 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
// Not using recursive types because it is recommend to use those carefully | |
// for performance reasons | |
type Awaited<T> = T extends PromiseLike<infer U> ? U : T; | |
// debounce function which resolves with undefined when call has been cancelled | |
// The function returns a promise which resolves with awaited return value of the callback | |
// Except if the callback call was canceled because of the debouncing in which case | |
// the promise resolves with undefined | |
export default function debounce<T>( | |
// eslint-disable-next-line @typescript-eslint/no-explicit-any | |
func: (...args: any[]) => T, | |
wait: number, | |
) { | |
let timeout: NodeJS.Timeout | null = null; | |
let _resolve: ( | |
value: Awaited<T | undefined> | PromiseLike<Awaited<T>>, | |
) => void; | |
// eslint-disable-next-line @typescript-eslint/no-explicit-any | |
return function (this: any, ...args: any[]) { | |
return new Promise<Awaited<T> | undefined>((resolve, reject) => { | |
if (timeout) { | |
if (_resolve) { | |
// Debounced function called again before timeout passed | |
// The previous call resolves with undefined | |
_resolve(undefined); | |
} | |
clearTimeout(timeout); | |
} | |
_resolve = resolve; | |
timeout = setTimeout(() => { | |
timeout = null; | |
try { | |
// @ts-expect-error nested promise | |
resolve(func.apply(this, args)); | |
} catch (e) { | |
reject(e); | |
} | |
}, wait); | |
}); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment