防抖与节流(原生js)

325 阅读2分钟

应用场景

在用户交互功能的一些设计上,需要针对用户的一些操作来回调我们的事件处理函数或者发起一些特定的ajax请求,有时用户会频繁的触发这一事件,而造成我们做一些过剩切没必要的回调或请求。因此,我们需要对用户的交互进行一些限定。

模拟场景:

    <button id="btn">发起请求</button>
    <script>
        const btn = document.getElementById('btn')
        btn.addEventListener('click',()=>{
            console.log('发起ajax请求');
        })
    </script>

防抖函数

点击一个按钮,然后我们发起请求将新的数据反馈回来。但有些用户手抽筋,
疯狂点击,导致我们发起了多个请求,但最终反馈的数据依旧只是同一个数据,
而且我们在拿完数据后要渲染页面,会重复渲染一模一样内容的页面,使得页面会抖动,顾名思义我们需要用到防抖函数

因此,我们欲实现:不管用户点击了多少次,只要这相邻的两次触发间隔时间不算长,
待用户消停了,我们将最后反馈一次即可,避免了回调和请求的浪费。
/**
 *  封装一个防抖函数
 * @param {Function} fn 
 * @param {number} gap 默认间隔时长为1s
 * @returns 一个具有防抖功能的函数
 */
function debounce(fn, gap = 1000) {
    // 声明一个定时器容器存放在函数闭包里
    let timer = null
    // 返回具有防抖功能,又能调用原函数的一个新函数
    return function () {
        if (timer) {
            // 当发现闭包中上一次的定时器还存在时,我们就将它清掉
            clearTimeout(timer)
        }
        // 让原函数在延迟到一定时间后执行
        timer = setTimeout(() => {
            fn.apply(null, arguments)
        }, gap);
    }
}
   // 业务代码
    const newFn = debounce(fn)  // 得到一个防抖且具有原功能的函数
    const btn = document.getElementById('btn')
    btn.addEventListener('click', newFn)

节流函数

明白的防抖函数,我们便能更快理解什么是节流函数,二者大同小异,都是针对一个函数被频繁地调用,然后我们进行二种不同的控制。防抖函数即只要用户不消停的触发事件,我们都不理睬,只等到用户消停了我们再反馈。而节流函数则是将不间断的事件分割,在一定时间间隔时才反馈一次。
     /**
     *  节流函数
     * @param {Function} fn 
     * @param {number} gap 
     * @returns 一个具有节流功能函数
     */
       function throttle(fn, gap = 1000) {
       let timer = null
       return function () {
           // 如果闭包中已经存在一个延时执行的函数时,我们不理睬
           if (!timer) {
               timer = setTimeout(() => {
                   fn.apply(null, arguments)
                   timer = null
               }, gap);
           }
       }
   }
   const fn = () => {
       console.log('拿到value:', ip.value);
   }
   const newFn = throttle(fn)
   const ip = document.getElementById('ip')
   ip.addEventListener('input', newFn)