前端优化:防抖和节流

298 阅读2分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

问题起源

页面中常见的监听浏览器滚动事件,窗口的 onresize 事件以及输入框实时监听输入事件都会导致这些事件会被高频触发,而如果此类事件的执行函数比较复杂,响应跟不上事件的触发的话,就会导致页面卡顿假死的现象,从而让用户体验非常糟糕,浏览器的性能是有限的,不应该浪费在这里,所以就出现了函数防抖(debounce)函数节流(throttling)的策略

问题的解决方案

  • 函数防抖(debounce):当事件触发时,设定一个周期延迟执行动作,如果期间再次触发,则重新设定周期,知道周期结束才执行动作。
  • 前缘防抖:执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定。
  • 函数节流(throttling):固定周期内,只执行一次动作,若有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期。 :延迟:周期结束后执行动作; 前缘:执行动作后再开始周期

应用场景

  • 函数防抖(debounce):事件触发是高频次但是有停顿,如: 页面 resize 事件
  • 函数节流(throttling):事件连续不断高频触发时, 如: 监听浏览器滚动事件

实现方法

// 函数防抖,如果短时间内大量触发同一事件,只会执行最后一次函数
function debounce(fn, wait) {
    var timer = null;
    return function() {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, Array.prototype.slice.call(arguments, 0)), wait);
    }
}

// 函数节流,如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效
function throttle(fn, wait) {
    var timer = null;
    return function() {
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(this, Array.prototype.slice.call(arguments, 0));
                timer = null;
            }, wait);
        }
    }
}

(求关注)

欢迎关注我的公众号:A纲 Coder,获得日常干货推送。最后再次感谢您的阅读,我是程序猿憨憨