网上很多节流防抖的写法都是错的,不想大家被误导,看这里吧,正解!
防抖(debounce)
普通版
普通版防抖是在满足要求后最后才执行一次。常见场景是输入查询
。
// 普通版
function debounce (fn, wait) {
let timer = null
return function (...args) {
const context = this
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}
立即执行版
立即执行版是立即就执行,最后不再执行。总的还是执行一次。常见场景是提交按钮
。
举例说明:一个提交按钮,假如
1s
内连续点击不执行,如果用户连续点击10s
(点击间隔都没有超过1s
),那么【普通版】会在第11s
结束时才执行,【立即执行版】会在第一次点击后立马执行,最后不执行。
// 立即执行版
function debounce (fn, wait) {
let timer = null
return function (...args) {
const context = this
if (timer) {
clearTimeout(timer)
}
const canRun = !timer
timer = setTimeout(() => {
timer = null
}, wait)
if (canRun) {
fn.apply(context, args)
}
}
}
混合版
可以根据用户需要使用上面2个版本哪一个,通过一个参immediate
控制。
/**
* @desc 函数防抖
* @param fn 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce (fn, wait, immediate) {
let timer = null
return function (...args) {
const context = this
if (timer) {
clearTimeout(timer)
}
if (immediate) {
const canRun = !timer
timer = setTimeout(() => {
timer = null
}, wait)
if (canRun) {
fn.apply(context, args)
}
} else {
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}
}
混合版,带取消功能
/**
* @desc 函数防抖
* @param fn 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce (fn, wait, immediate) {
let timer = null
const debounceFn = function (...args) {
const context = this
if (timer) {
clearTimeout(timer)
}
if (immediate) {
const canRun = !timer
timer = setTimeout(() => {
timer = null
}, wait)
if (canRun) {
fn.apply(context, args)
}
} else {
timer = setTimeout(() => {
fn.apply(context, args)
}, wait)
}
}
debounceFn.cancel = () => {
if (timer) {
clearTimeout(timer)
timer = null
}
}
return debounceFn
}