防抖与节流

95 阅读2分钟

一、是什么

1.1 防抖:

就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

例如:坐电梯的时候,如果电梯检测到有人进来(触发事件),就会多等待 10 秒,此时如果又有人进来(10秒之内重复触发事件),那么电梯就会再多等待 10 秒。

在上述例子中,电梯在检测到有人进入 10 秒钟之后,才会关闭电梯门开始运行,因此,“函数防抖”的关键在于,在 一个事件 发生 一定时间 之后,才执行 特定动作

1.2 节流

当持续触发事件时,保证一定时间段内只调用一次事件处理函数。

二、实现

2.1 防抖

实现方式:定时器。

 // 防抖-n触发一次,如再触发再重新计时。
    function debounce(fn, delay) {

        if (typeof fn != 'function') {
            throw new TypeError('FUN_ERROR_TEXT');
        }

        let timer = null; // 计时器
        return function () {
            if (timer) {
                clearTimeout(timer) // 进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
                timer = setTimeout(fn, delay)
            } else { // 进入该分支说明当前并没有在计时,那么就开始一个计时
                timer = setTimeout(fn, delay)
            }
        }
    }
    // 处理函数
    function handle() {
        console.log(Math.random())
    }

    window.addEventListener('scroll', debounce(handle, 500))

应用场景

  1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
  2. 用户名、手机号、邮箱输入验证;
  3. 浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。

2.2 节流

主要有两种实现方法:定时器和时间戳。接下来分别用两种方法实现throttle~

定时器版本:

 // 节流函数
    function throttle(fn, delay) {
        let flag = true;
        return function () {
            if (!flag) {
                return false; // 休息,暂不接客
            }
            // 工作时间
            flag = false;
            setTimeout(() => {
                fn.apply(this, arguments);
                flag = true;
            }, delay)
        }
    }
    // 处理函数-定时器
    function handle() {
        console.log(Math.random())
    }
    function getMathRandom () {
        throttle(handle, 1000)();
    }

时间戳版本:

function throttle(func, wait) {
    let previous = 0;
    return function() {
        let now = Date.now();
        if (now - previous > wait) {
            func.apply(this, arguments);
            previous = now;
        }
    }
}

应用场景:

  1. 按钮点击事件,防止用户多次提交。(loading->flag->节流)
  2. 拖拽事件
  3. onScol
  4. 计算鼠标移动的距离(mousemove)