自定义去抖动功能不适用于匿名功能
Custom debounce function not working with anonymous functions
我正在尝试创建自定义去抖功能:
const debounced = [];
const cancelFunc = timeout => () => {
clearTimeout(timeout);
};
function debounce(fn, wait, ...args) {
let d = debounced.find(({ func }) => func === fn);
if (d) {
d.cancel();
} else {
d = {};
debounced.push(d);
}
d.func = fn;
d.timeout = setTimeout(fn, wait, ...args);
d.cancel = cancelFunc(d.timeout);
}
如果我使用命名函数,它会按预期工作:
debounce(foo, 1000); // called once with 5 clicks in 1 second
但我无法让它与匿名函数一起工作:
debounce(() => { foo(5); }, 1000); // called 5 times with 5 clicks in 1 second
如@SLaks所述"Each call creates a separate function, so you won't find it in the array."
所以你只需要在数组中存储一些东西来匹配它,你可以使用.toString()
// ================
const debounced = [];
const cancelFunc = timeout => () => {
clearTimeout(timeout);
};
function debounce(fn, wait, ...args) {
let d = debounced.find(({ funcString }) => funcString === fn.toString());
if (d) {
d.cancel();
} else {
d = {};
debounced.push(d);
}
d.func = fn;
d.funcString = fn.toString()
d.timeout = setTimeout(fn, wait, ...args);
d.cancel = cancelFunc(d.timeout);
}
// ================
function foo(value) {
console.log('value:', value)
}
function onClickBroken() {
debounce(() => { foo(5); }, 1000);
}
<button onClick="onClickBroken()">Click me 5 times</button>
发生这种情况是因为您的 find
状况。让我们回过头来,考虑一下这段代码:
if (
(function(){ return 1 }) === (function(){ return 1 })
) {
console.log('The functions are equal');
} else {
console.log('The functions are NOT equal');
}
// logs 'The functions are NOT equal'
即使我写了两个相同的匿名函数,它们并不彼此严格相等。当您传入该匿名函数时,这实际上就是您正在做的事情。因此,当您在数组中搜索以前找到的函数时,它永远找不到匹配项,因为每次调用 debounce(() => { foo(5); }, 1000);
时,它 都会创建一个新函数 。由于永远找不到匹配项,因此永远不会取消。
我正在尝试创建自定义去抖功能:
const debounced = [];
const cancelFunc = timeout => () => {
clearTimeout(timeout);
};
function debounce(fn, wait, ...args) {
let d = debounced.find(({ func }) => func === fn);
if (d) {
d.cancel();
} else {
d = {};
debounced.push(d);
}
d.func = fn;
d.timeout = setTimeout(fn, wait, ...args);
d.cancel = cancelFunc(d.timeout);
}
如果我使用命名函数,它会按预期工作:
debounce(foo, 1000); // called once with 5 clicks in 1 second
但我无法让它与匿名函数一起工作:
debounce(() => { foo(5); }, 1000); // called 5 times with 5 clicks in 1 second
如@SLaks所述"Each call creates a separate function, so you won't find it in the array."
所以你只需要在数组中存储一些东西来匹配它,你可以使用.toString()
// ================
const debounced = [];
const cancelFunc = timeout => () => {
clearTimeout(timeout);
};
function debounce(fn, wait, ...args) {
let d = debounced.find(({ funcString }) => funcString === fn.toString());
if (d) {
d.cancel();
} else {
d = {};
debounced.push(d);
}
d.func = fn;
d.funcString = fn.toString()
d.timeout = setTimeout(fn, wait, ...args);
d.cancel = cancelFunc(d.timeout);
}
// ================
function foo(value) {
console.log('value:', value)
}
function onClickBroken() {
debounce(() => { foo(5); }, 1000);
}
<button onClick="onClickBroken()">Click me 5 times</button>
发生这种情况是因为您的 find
状况。让我们回过头来,考虑一下这段代码:
if (
(function(){ return 1 }) === (function(){ return 1 })
) {
console.log('The functions are equal');
} else {
console.log('The functions are NOT equal');
}
// logs 'The functions are NOT equal'
即使我写了两个相同的匿名函数,它们并不彼此严格相等。当您传入该匿名函数时,这实际上就是您正在做的事情。因此,当您在数组中搜索以前找到的函数时,它永远找不到匹配项,因为每次调用 debounce(() => { foo(5); }, 1000);
时,它 都会创建一个新函数 。由于永远找不到匹配项,因此永远不会取消。