带有可取消包装的 Vanilla js 变体
请注意,此解决方案不需要您修改外部 debounce 函数,甚至不需要使用外部函数。逻辑在 wrapepr 函数中完成。提供去抖代码。
允许在其去抖动期间取消已调用函数的最简单方法是从可取消的包装中调用它。真的只需添加 3 行代码和一个可选条件。
const doTheThingAfterADelayCancellable = debounce((filter, abort) => {
if (abort) return
// here goes your code...
// or call the original function here
}, /*debounce delay*/500)
function onFilterChange(filter) {
let abort = false
if (filter.length < 3) { // your abort condition
abort = true
}
// doTheThingAfterADelay(filter) // before
doTheThingAfterADelayCancellable(filter, abort) // new wrapped debounced call
}
您可以通过abort = true 再次调用它来取消它。
它的工作方式是清除之前的超时 fn 并像往常一样设置一个新的超时,但现在使用 if (true) return 路径。
您也可以通过其他代码手动执行此操作...
doTheThingAfterADelayCancellable(null, true)
...或将其包装起来并使用cancelBounce()调用
function cancelBounce() {
doTheThingAfterADelayCancellable(null, true)
}
作为参考,这是取自 Underscore 的经典 debounce 函数。在我的示例中它保持不变。
// taken from Underscore.js
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
export function debounce(func, wait, immediate) {
let timeout
return function() {
let context = this, args = arguments
let later = function() {
timeout = null
if (!immediate) func.apply(context, args)
}
let callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, wait)
if (callNow) func.apply(context, args)
}
}