簡體   English   中英

打字稿去抖動函數不調用作為參數傳遞的函數

[英]Typescript debounce function not calling function passed as parameter

我正在嘗試使用typescript編寫去抖動函數。

我在這里找到了一個例子。 代碼如下:

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)
  }
}

問題是:

  • 在指定的超時后未調用作為參數傳遞的函數
  • 我不能使用 lodash 或任何其他外部庫,因為我試圖避免向這個項目添加新的依賴項。

謝謝。

你如何使用你的debounce功能? 我准備小提琴,你可以在這里查看工作解決方案

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');

嗯,這不是打字稿的麻煩

這是對 Saveli Tomac 出色答案的補充。

在評論中我說我認為實施不是特別好。 特別是它有兩個問題:

  1. 它沒有立即的選擇。 野外的大多數去抖動實現(包括您在問題中鏈接的那個)都有這個。
  2. 返回的函數忽略this值。

這是修復這些問題的示例:

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;
  }
};

打字稿游樂場

如果函數的結果對你有用,你可以試試我為函數接口寫的擴展方法:

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

用法很簡單,就像通過使用trailingDebounce(wait: number)leadingDebounce(wait: number)trailingThrottle(wait: number)leadingThrottle(wait: number)函數來創建函數的去抖動或節流版本一樣簡單。 下面是一個例子:


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,
);

這導致:

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

如果使用addOffsetTrailingDebounce函數,結果為:

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

如果使用addOffsetLeadingThrottle函數,結果是:

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

如果使用addOffsetTraillingThrottle函數,結果是:

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

export const debounce = (callback: (...params: any[]) => any, delay:number) => {
    let inDebounce: ReturnType<typeof setTimeout>;

    return function (this:any, ...args: any[]) {
        clearTimeout(inDebounce);
        inDebounce = setTimeout(() => callback.apply(this, args), delay);
    };
};

window.addEventListener('scroll', debounce(() => console.log('test'), 250));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM