打字稿去抖功能不调用作为参数传递的函数
Typescript debounce function not calling function passed as parameter
我正在尝试使用 typescript 编写一个 debounce 函数。
我在 here 中找到了一个例子。代码如下:
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
功能?我准备了 fiddle,你可以检查工作解决方案 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');
好吧,这不是打字稿的问题
这是对 Saveli Tomac 出色回答的补充。
我在评论中说我认为实现不是特别好。特别是它有两个问题:
- 它没有立即选项。大多数去抖实现(包括您在问题中链接的那个)都有这个。
- 返回的函数忽略
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));
我正在尝试使用 typescript 编写一个 debounce 函数。
我在 here 中找到了一个例子。代码如下:
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
功能?我准备了 fiddle,你可以检查工作解决方案 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');
好吧,这不是打字稿的问题
这是对 Saveli Tomac 出色回答的补充。
我在评论中说我认为实现不是特别好。特别是它有两个问题:
- 它没有立即选项。大多数去抖实现(包括您在问题中链接的那个)都有这个。
- 返回的函数忽略
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));