函数防抖(debounce)和函数节流(throttle)

防抖(debounce)


  • 如果下达该命令后,在t毫秒内再次下达该命令,只执行新命令
  • 最终效果:对于连续动作(动作间的时间间隔小于t),以最后一次为准
  • 实现方法:对于一个事件,每次都销毁一个计时器并创建一个计时器,具体的操作放在计时器里面;当操作过于频繁,那么计时器会被不断的销毁和创建,里面的操作只有当最后一个没有被销毁的时候,才会触发。

范例

let command
document.body.onscroll = () => {
    console.log('这里每次都执行')
    if(command){
        clearTimeout(command)
    }
    command = setTimeout(() => {
        console.log('这里只执行连续动作的最后一次')
    }, 1000)
}

封装

这里的设计模式也叫装饰模式

function debounce(fn, wait) {
    let timer = null
    return function() {
        if(timer)
            clearTimeout(timer)
        timer = setTimeout(() => fn.apply(this, arguments), wait)
    }
}

let fn = () => console.log('这里只执行连续动作的最后一次')
fn = debounce(fn, 1000)

document.body.onscroll = fn

节流(throttle)


  • 从上一次命令结束开始的一段时间范围t内,如果多次下达命令,则只执行当前时间段t内的第一次命令。
  • 最终效果:对于连续动作,会过滤出部分动作,让这些过滤后的动作之间的执行间隔大于等于t
  • 实现方法:使用nowTime的时间流

范例

let gapTime = 1000
let lastTime = null
let nowTime = null
let fn = () => console.log('我执行了')
document.body.onscroll = () => {
    nowTime = Date.now()
    if(!lastTime || nowTime - lastTime > gapTime) {
        fn()
        lastTime = nowTime
    }
}

封装

function throttle(fn, gapTime) {
    let lastTime = null
    let nowTime = null
    return function() {
        nowTime = Date.now()
        if(!lastTime || nowTime - lastTime > gapTime) {
            fn()
            lastTime = nowTime
        }
    }
}

let fn = () => console.log('我执行了!')
fn = throttle(fn, 1000)
document.body.onscroll = fn

总结


  1. 函数防抖和函数节流都是防止某一时间频繁触发,但是这两兄弟之间的原理却不一样。
  2. 函数防抖是某一段时间内只执行一次,而函数节流是间隔时间执行。

应用场景


  • debounce
    • search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
    • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
  • throttle
    • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
    • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

你可能感兴趣的:(函数防抖(debounce)和函数节流(throttle))