Typescript debounce function not calling function passed as parameter
Solution 1
How do you use your debounce
function? I prepare fiddle, you can check working solution here
function debounce<Params extends any[]>(
func: (...args: Params) => any,
timeout: number,
): (...args: Params) => void {
let timer: NodeJS.Timeout
return (...args: Params) => {
clearTimeout(timer)
timer = setTimeout(() => {
func(...args)
}, timeout)
}
}
function test(message) {
alert(message);
}
const debouncedTest = debounce(test, 2000);
debouncedTest('message');
Well, it's not typescript troubles
Solution 2
This is intended as a supplement to Saveli Tomac's excellent answer.
In the comments I said I didn't think that implementation was particularly good. In particular it has two problems:
- It doesn't have an immediate option. Most debounce implementations in the wild (including the one you linked in your question) have this.
- The returned function ignores the
this
value.
Here's an example that fixes these:
const debounce = (n: number, fn: (...params: any[]) => any, immed: boolean = false) => {
let timer: number | undefined = undefined;
return function (this: any, ...args: any[]) {
if (timer === undefined && immed) {
fn.apply(this, args);
}
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), n);
return timer;
}
};
Related videos on Youtube
Lucas Meine
Always inventing, improving and creating. I'm a software engineer, Microsoft certified professional and casual StackOverflow user that likes to answer PHP and jquery questions because I miss the old times. Feel free to add me on LinkedIn :) I also host Meine's Rock Bar where I talk about a lot of stuff, including software development How to write a good answer to a question How to create a Minimal, Reproducible Example
Updated on June 04, 2022Comments
-
Lucas Meine almost 2 years
I'm trying to write a debounce function with typescript.
I found an example of it in here. Code follows:
export function debounce<Params extends any[]>( func: (...args: Params) => any, timeout: number, ): (...args: Params) => void { let timer: NodeJS.Timeout return (...args: Params) => { clearTimeout(timer) timer = setTimeout(() => { func(...args) }, timeout) } }
Problem is:
- Function passed as a parameter is not getting called after the specified timeout
- I can't use lodash or any other external library because I'm trying to avoid adding new dependencies to this project.
Thanks.
-
Jared Smith over 4 years@Fluffremovalservice I think it works well enough for what it is (see the answer below), but I'm used to debounce having an immediate option, and those typings look...like the simplest thing that could possibly work rather than something that would actually be a production implementation.
-
Lucas Meine over 4 yearsActually, I'm getting Type 'Timeout' is not assignable to type 'number' with your example.
-
svltmccc over 4 years@Fluffremovalservice setTimeout from browser returns number (timeout id), but you call it from nodejs. You can change type for timer to NodeJS.Timeout | undefined
-
Lucas Meine over 4 yearsTried it, and got Type 'Timeout' is not assignable to type 'number' in the clearTimeout(timer) line. Am I still missing something?
-
Jared Smith over 4 years@Fluffremovalservice I'm not getting error in the playground, see the updated link. What version of Typescript?
-
svltmccc over 4 years@Fluffremovalservice try call global.clearTimeout instead of clearTimeout
-
svltmccc over 4 years@JaredSmith you run your code in browser environment and it's normal behaviour