1、前端中的节流防抖

在Web前端中, 所谓节流防抖是为了防止用户在较短时间内的多次操作引发的动作执行,其是前端项目常用的一种优化手段。比如,用户在1秒内多次点击点赞按钮导致点赞请求发送多次;防止在用户拉动滚动条时多次触发加载更多的情况。

2、节流

何为节流

所谓节流,指的是在一段时间之内,用户的多次请求只会执行一次(确保在每一个特定的时间段内被执行一次)。换人话说就是高频率触发的事件, 在指定的单位时间内, 只响应第一次(前面触发的执行前,忽略后面的事件)。

代码实现

大概步骤如下:

  • 利用闭包保存一个flag变量, 然后返回一个函数
  • 第一次进入时会设置定时器(timeout时间之后再执行)
  • 后续在timeout时间之内再调用将不会执行(flag为false)
function throttle(fn, timeout) {
  let flag = true;
  return function() {
    if(flag) {
      setTimeout(() => {
        fn.call(this);
        flag = true;
      }, timeout);
    }
    flag = false;
  }
}

注意:自己好好理解下上面代码的逻辑, 面试时经常要手写这个代码。

3、防抖

何为防抖

所谓防抖,明面上看就是防止抖动,指的是为了防止快速且频繁的触发事件而导致多次执行事件函数,多次触发的事件只执行一次事件函数(仅在最后一次真正执行事件处理代码)。防抖要解决的问题: 假设一个用户高频点击一个按钮,点击按钮后会向后台发送请求,如果不使用防抖,就会发送许多重复的Ajax请求,造成服务器压力。使用防抖后,只会发送一次Ajax请求,可以有效地减缓服务器的压力。

防抖原理: 将多次高频操作优化为只在最后一次执行, 某个函数在某段时间内,无论触发了多少次回调,都只执行最后一次。通常的使用场景是:用户输入,只需在输入完成后做一次输入校验即可。

代码实现

大概步骤如下:

  • 利用闭包保存一个timer变量, 然后返回一个函数
  • 第一次进入里面的函数时会设置定时器
  • 当有新的触发时(wait时间内),若存在定时器则清空, 然后开始设置新的定时器, 重新计时
  • 当wait时间过了之后没有新的触发时, 上次设置的定时器里面的函数执行

原生js代码如下:

function debounce(func, wait) {
  let timer = null;
  return function(...args) {
    // 有新的触发,则把定时器清空 
    if(timer) {
      clearTimeout(timer);
    }
    // 重新计时
    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait)
  }
}

注意:自己好好理解下上面代码的逻辑, 面试时经常要手写这个代码。

4、节流和防抖的区别

  • 相似点:都是为应对事件持续频繁发生,造成前端性能下降或对后端服务造成的压力。
  • 区别:节流会不断的触发(在n秒内只执行一次),而防抖仅在最后一次触发(延迟n秒执行, 若在n秒内重复触发则重新开始计时)。
  • 防抖适用场景如下:
    • 限制鼠标连击触发(比如给按钮添加防抖,防止表单多次提交)
    • 每次resize/scroll触发统计事件
    • 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)
  • 节流适用场景如下:
    • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
    • 搜索联想(keyup)
    • 监听滚动事件判断是否到页面底部自动加载更多