返回

手撕代码系列(三):一石二鸟探寻防抖和节流的多种实现思路

前端

在前端开发中,我们经常会遇到这样的场景:用户在操作某个元素时,我们希望在用户停止操作后执行某个函数。比如,当用户在输入框中输入时,我们希望在用户停止输入后才进行搜索。或者当用户在页面上滚动时,我们希望在用户停止滚动后才加载更多内容。

为了实现这样的需求,我们可以使用防抖(debounce)和节流(throttle)两种技术。

防抖

防抖的核心思想是:当外界不再变化时,再去做响应。

举个例子,当用户在输入框中输入时,如果我们每次输入都向服务器发送请求,那么就会无意义地消耗服务器资源。因此,我们可以使用防抖来限制请求的发送频率,比如每隔500毫秒发送一次请求。这样,当用户输入速度很快时,服务器也不会收到太多的请求。

节流

节流的核心思想是:不管外界如何变化,始终保持着自己的响应频率。

举个例子,当用户在页面上滚动时,如果我们每次滚动都加载更多内容,那么页面就会变得非常卡顿。因此,我们可以使用节流来限制加载内容的频率,比如每隔100毫秒加载一次内容。这样,当用户滚动速度很快时,页面也不会出现卡顿的情况。

防抖和节流的实现

防抖和节流的实现有很多种方法,这里介绍两种最常用的方法:

  1. setTimeout()方法

我们可以使用setTimeout()方法来实现防抖和节流。

// 防抖
function debounce(func, wait) {
  let timer = null;
  return function() {
    let args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
}

// 节流
function throttle(func, wait) {
  let lastTime = 0;
  return function() {
    let now = Date.now();
    if (now - lastTime >= wait) {
      func.apply(this, arguments);
      lastTime = now;
    }
  };
}
  1. requestAnimationFrame()方法

我们还可以使用requestAnimationFrame()方法来实现防抖和节流。

// 防抖
function debounce(func, wait) {
  let timer = null;
  return function() {
    let args = arguments;
    if (timer) {
      cancelAnimationFrame(timer);
    }
    timer = requestAnimationFrame(() => {
      func.apply(this, args);
    });
  };
}

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

防抖和节流的使用场景

防抖和节流在前端开发中有很多应用场景,这里列举几个常见的场景:

  • 搜索框 :当用户在搜索框中输入时,我们使用防抖来限制请求的发送频率,避免无意义地消耗服务器资源。
  • 页面滚动 :当用户在页面上滚动时,我们使用节流来限制加载内容的频率,避免页面卡顿。
  • 按钮点击 :当用户点击按钮时,我们使用节流来限制按钮的点击频率,避免按钮被多次触发。
  • 窗口调整大小 :当用户调整窗口大小时,我们使用节流来限制窗口调整大小的事件触发频率,避免浏览器卡顿。

总结

防抖和节流是前端性能优化必备的两个小技巧。掌握了这两个小技巧,我们可以轻松地优化页面的性能,提高用户体验。