Typescript debounce function not calling function passed as parameter

梦想的初衷 提交于 2021-02-08 15:13:26

问题


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.


回答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




回答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:

  1. It doesn't have an immediate option. Most debounce implementations in the wild (including the one you linked in your question) have this.
  2. 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;
  }
};

Typescript Playground




回答3:


If the result of the function is useful for you, you can try the extension methods that I wrote for the function interface:

https://gist.github.com/falahati/fda618a9b59bb7d7f33b9ba0d5ef01a3

Usage is as simple as creating a debounce or throttled version of your function by using the trailingDebounce(wait: number), leadingDebounce(wait: number), trailingThrottle(wait: number) or the leadingThrottle(wait: number) function. Here is an example:


class RelativeOffsetCalculator {
    public addOffsetTrailingDebounce = this.addOffset.trailingDebounce(500);
    public addOffsetLeadingDebounce = this.addOffset.leadingDebounce(500);
    public addOffsetTrailingThrottle = this.addOffset.trailingThrottle(500);
    public addOffsetLeadingThrottle = this.addOffset.leadingThrottle(500);

    private _offset: number;

    constructor(offset: number) {
        this._offset = offset;
    }

    public addOffset(base: number): number {
        return base + this._offset;
    }
}

const instance = new RelativeOffsetCalculator(1);
let executions = 0;

// Call each 100ms for 10 times at a total of a second, should get limited
const intervalTimer = window.setInterval(
    () => {
        if (executions >= 10) {
            window.clearInterval(intervalTimer);
            return;
        }

        instance.addOffsetLeadingDebounce(executions).then(
            (result) => console.log(result),
            (error) => console.warn(error),
        );
        executions++;
    },
    100,
);

// A later call at 2 seconds mark, should not get limited
window.setTimeout(
    () => {
        instance.addOffsetLeadingDebounce(100).then(
            (result) => console.log("Late Execution: ", result),
            (error) => console.warn("Late Execution: ", error),
        );
    },
    (10 * 100) + 1000,
);

This results in:

1 1 1 1 1 1 1 1 1 1 Late Execution: 101,

If the addOffsetTrailingDebounce function is used, the results are:

10 10 10 10 10 10 10 10 10 10 Late Execution: 101

and if the addOffsetLeadingThrottle function is used, the results are:

1 1 1 1 1 5 5 5 5 5 Late Execution: 101

and if the addOffsetTraillingThrottle function is used, the results are:

5 5 5 5 5 10 10 10 10 10 Late Execution: 101



来源:https://stackoverflow.com/questions/59104425/typescript-debounce-function-not-calling-function-passed-as-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!