防抖和节流

185 阅读2分钟

遇到一个需求,页面需要加载一个数据表,但是请求的特别慢,如果用户多次点击按钮,那么此时就会不断触发这个请求,因为不断发请求,所以会导致页面不断乱刷新,可以说体验感特别差。所以一直在思考怎么解决这个bug。突然想到防抖和节流,我之前也一直没有搞清楚,这次一次性搞清,再来试图解决一下页面这个bug。

函数防抖

首先考虑的是防抖,什么是防抖。在页面中,诸如click,mousemove这些事件可能在短时间内会被多次执行,比如多次点击一个按钮,那么如果一次点击就要发一次请求,则会造成内存的过度使用。所以我们监听一个定时器,当定时器被点击的时候我们用一个定时器去监听,设置一定的时间后再去触发事件。这样的情况下,如果这个按钮再次被点击,那么因为监听了定时器,此时定时器会被替代,重新开始计算时间,这就是函数防抖的原理,这里给出原始版本的函数防抖:

let timer = ""
export function debounce(fn,time){
    window.clearTimeout(timer);
    timer = setTimeout(()=>{
        fn()
    },time)
}

但是以上的代码,time是一个外层的变量,这样会污染环境,所以我们考虑用闭包的方式把变量包含在父作用域中,这样变量一直会限制在局部作用域中而不会污染整个环境了。

export function debounce(fn,time){
    let timer;
    return ()=>{
        const _this = this;
        if (timer) clearTimeout(timer)
        timer = setTimeout(()=>{
            fn.apply(_this)
        },time)
    }
}

函数节流

对上面减少触发次数不同的思路是节流。让函数在一段时间内只执行一次,这是这个思想的宗旨。比如之前的鼠标点击触发的请求,我们可以采用节流函数进行封装,这样能有效的减少点击之后发送的请求个数。 代码跟之前的防抖很类似。

export const throttle = (fn,time)=>{
    let timer
    return ()=>{
        const _this = this
        if (timer) return
        timer = setTimeout(()=>{
            fn.call(_this)
            //不同点在于触发后就清楚timer,从而使得下次进入函数的时候能再次触发一个节流函数
            timer = null
        },time)
    }
}

以上就是防抖和节流的思想和实现方式了,希望对我的项目有帮助