浅谈:防抖 与 节流

794 阅读3分钟

button 请求

<body>

    <button id="btn">提交</button>
    
    <script>

        let btn = document.getElementById('btn')

        btn.addEventListener('click', debounce(a,1000))

        function a() {

                console.log('提交成功');
                
            }        

    </script>

</body>

上面的代码当中,定义了一个button按钮,获取其dom结构,并监听它的点击事件,只要点击了按钮,就会执行debounce函数,然后由debounce函数调用a,那么请大家来思考一下,该怎么写这个函数呢?并且让这个函数能够在你多次点击之后,不浪费网络资源,只发出一次申请(也就是只打印一次结果)呢?

很多人在想,我定义一个定时函数,每点击一下在一定时间后发出申请,然后在定义一个变量来控制这个定时函数不就好了,于是有了下面这段代码

示范

function debounce(fn, delay){

    let timer = 0

    return function(){

        timer++

       if(timer > 0){   

           setTimeout(()=>{

            timer = 0

        },delay)

    if(timer == 0){    
        fn()
    } }
    }
}

代码分析

传入参数delay作为定时器延迟时间,定义了timer = 0,然后自增,只要timer > 0,定时函数就执行,使timer变回0,然后再判断如果timer为0就调用fn,打印结果。逻辑思路是不是很清晰,但是代码能行的通吗?

很显然还有问题,你点击多次,在这里只是延迟了打印时间,也就是说,点击多次还是会发出多次申请,并且定时函数为异步函数,也就是说,我在下方已经先判断了timer是否为0,之后才判断timer是否大于0,这里就是两个思维漏洞,于是我们针对这两个问题做出相应调整。

在定时函数之前加个清除定时器的功能,那么只要你一直点击我就会清除上一次发出的请求,只会在你最后一次点击的时候间隔一秒发出请求,得到打印结果。

function debounce(fn, delay){

    let timer = null

    return function(){

        clearTimeout(timer)  //清除定时器

        timer = setTimeout(()=>{

            fn()

        },delay)

    }

}

可能看到这里你就大概明白了什么是防抖了。

防抖

概念

通俗来说,防抖就是在规定的时间内,没有触发第二次,那么就会去执行

比如上面的例子:如果我第二次或者之后不去点击button,那么会去执行打印操作,也就是说,最后一次点击才有效。

实现代码

function debounce(fn, delay){

    let timer = null

    return function(){

        let arg = arguments //接收参数

        clearTimeout(timer)

        timer = setTimeout(()=>{

            fn.apply(this,arg)    

        },delay)

    }

}

断点

概念

节流的概念则是,在规定的时间里就触发一次,也就是说你就算点击多次button请求,我也只发送一次,虽然实现效果和防抖一样,但是过程却不一样

代码实现

function throttle(fn,daley = 1000){

    let timer = null

    return function(){

        let arg = arguments

        let now = Date.now() //此次点击事件的时间

        if(now - timer >= daley){

            fn.call(this,arg)

            timer = Date.now() //保留点击时间给下一次使用

        }

    }

}

也是定义了一个变量timer,获取刚刚点击进去的时间,并在之后,定义now,获取此次点击事件的时间,之后保存此次点击的时间给下次点击使用,若是点击时间与上一次点击的时间的间隔不超过延迟的时间,那我们就发送请求,这也是可以实现的。

总结

关于防抖与节流,我们只是浅谈了一下,其实后续还有更复杂的操作,我们还是需要多学习一下的。

我是小白,我们一起学习,若有错误,敬请指出,谢谢大家!