Debounce防抖函数

119 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天

在实际的前端开发中,会有一些频繁的触发事件,像resize、mousemove、mousedown、keydown、keyup等。

下面是事件频繁触发的例子:
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>debounce</title>
  <style>
    #container{
      width: 100%;
      height: 300px;
      line-height: 300px;
      text-align: center;
      background-color: #555;
      color: #fff;
      font-size: 30px;
    }
  </style>
</head>
<body>
  <div id="container"></div>
  <script>
  let count = 1;
  const container = document.getElementById('container');
  const getUserAction = () => {
    container.innerHTML = count++
  }
  container.onmousemove = getUserAction;
  </script>
</body>

</html>

2022-11-23 12.06.14.gif 通过例子可以看到鼠标的mousemove事件频繁触发了多次,这就是频繁触发的事件。
假设这个事件是一个网络请求,我们不能让它多次发送请求,就需要用到防抖函数。

防抖函数

当我们只想在一段时间内触发函数一次,就需要防抖函数。在实际开发中,搜索框、文本字段自动保存和消除双击按钮都是debounce的用例。下面是一个简单防抖函数的示例:

function debounce(func, delay) {
    let timer = null;
    return (...param) => {
        if(timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(() => { func.apply(this, ...param); }, delay);
    }
 }
 

这就是一个简单的防抖函数,下面我们将它应用在我们上面的例子中

  container.onmousemove = debounce(getUserAction, 1000);

让我们来看一下效果

2022-11-23 14.52.50.gif 可以看到mousemove事件不会频繁的触发,1秒内只会触发一次。
防抖的原理就是无论你触发多少次事件,我一定会在最新的事件触发n秒后才会执行,如果在n秒内又触发了这个事件,就以新的事件触发的事件为准,n秒后执行。

防抖函数改进

假设我们想要立刻执行函数,等到停止触发事件的n秒后,再重新触发执行函数,需要怎么处理?
需要在防抖函数里加一个immediate参数,具体改进如下所示:

function debounce(func, delay, immediate) {
    let timer = null;
    return (...param) => {
        if (timer) {
            clearTimeout(timer);
        }
        if (immediate) {
            const callNow = !timer;
            timer = setTimeout(() => { timer = null }, delay);
            if (callNow) {
                func.apply(this, param);
            }
        } else {
            timer = setTimeout(() => { func.apply(this, param); }, delay);
        }
    }
}

我们将改进后的防抖函数运用在示例中:

  container.onmousemove = debounce(getUserAction, 1000, true);

效果如下:

2022-11-23 16.54.32.gif

以上就是有关防抖函数的一些知识和例子,供自己记录和掘友们参考~