]> Untitled Git - lemmy-ui.git/blob - src/shared/utils/helpers/debounce.ts
reset, merge issues
[lemmy-ui.git] / src / shared / utils / helpers / debounce.ts
1 export function debounce<T extends any[], R>(
2   func: (...e: T) => R,
3   wait = 1000,
4   immediate = false
5 ) {
6   // 'private' variable for instance
7   // The returned function will be able to reference this due to closure.
8   // Each call to the returned function will share this common timer.
9   let timeout: NodeJS.Timeout | null;
10
11   // Calling debounce returns a new anonymous function
12   return function () {
13     // reference the context and args for the setTimeout function
14     const args = arguments;
15
16     // Should the function be called now? If immediate is true
17     //   and not already in a timeout then the answer is: Yes
18     const callNow = immediate && !timeout;
19
20     // This is the basic debounce behavior where you can call this
21     //   function several times, but it will only execute once
22     //   [before or after imposing a delay].
23     //   Each time the returned function is called, the timer starts over.
24     clearTimeout(timeout ?? undefined);
25
26     // Set the new timeout
27     timeout = setTimeout(function () {
28       // Inside the timeout function, clear the timeout variable
29       // which will let the next execution run when in 'immediate' mode
30       timeout = null;
31
32       // Check if the function already ran with the immediate flag
33       if (!immediate) {
34         // Call the original function with apply
35         // apply lets you define the 'this' object as well as the arguments
36         //    (both captured before setTimeout)
37         func.apply(this, args);
38       }
39     }, wait);
40
41     // Immediate mode and no wait timer? Execute the function..
42     if (callNow) func.apply(this, args);
43   } as (...e: T) => R;
44 }