在开发中我们经常会遇见一些频繁触发的事件,比如resize、scroll、mousemove等。那如果这些事件是复杂的回调函数或是数据请求,连续的被触发之后,浏览器反应不过来,就会出现卡顿的现象,为了解决这个问题,就出现了两种解决方案:防抖(debounce)和 节流(throttle)

防抖(debounce)

原理:触发高频事件后n秒内,函数只会执行一次,如果在一个事件触发的n秒内再次触发这个事件,那会以新的触发时间重新计算。总之,就是在触发完事件的n秒内不再触发事件,才会再执行函数。

实现:

function debounce(fn, wait) {

        var timer = null;

        return function () {

            clearTimeout(timer);

            timer = setTimeout(() => {

                fn.apply(this, arguments);

            }, wait);

        }

    }

若想立即执行并在n秒内取消 debounce 函数的做法(immediate参数判断是否是立刻执行)

function debounce(fn, wait, immediate) {

    var timer, result;

    var debounced = function () {

        if (timer) clearTimeout(timer);

        if (immediate) {

            // 如果已经执行过,不再执行

            var callNow = !timeout;

            timer = setTimeout(() => {

                timer = null;

            }, wait);

            if (callNow) result = func.apply(this, arguments)

        }

        else {

            timer = setTimeout(() => {

                fn.apply(this, arguments);

            }, wait);

        }

        return result;

    };

    debounced.cancel = function() {

        clearTimeout(timer);

        timer = null;

    };

    return debounced;

}

节流(throttle)

原理:持续触发事件,每隔一段时间,只执行一次函数。就是说会稀释函数的执行频率。

实现:关于节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。

使用时间戳:

function throttle(fn, wait) {

      var previous = 0;

      return function () {

          var now = +new Date();

          if (now – previous > wait) {

              fn.apply(this, arguments);

              previous = now;

          }

      }

  }

使用定时器:当事件触发时,设置一个定时器,再次触发事件时,如果定时器存在,就不执行,直到执行定时器,执行函数,清空定时器。

function throttle(fn, wait) {

    var timer;

    var previous = 0;

    return function() {

        if (!timer) {

            timer = setTimeout(() => {

                timer = null;

                fn.apply(this, arguments)

            }, wait)

        }

    }

}

比较以上两种方法:

时间戳方法事件会立刻执行,定时器方法事件会在 n 秒后第一次执行;

时间戳方法事件停止触发后没有办法再执行事件,定时器方法事件停止触发后依然会再执行一次事件。

版权声明:本文为QueenZhang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/QueenZhang/p/12172449.html