JS 防抖与节流

57 阅读2分钟

防抖和节流都是用来控制函数执行频率的技术。

它们的区别在于:

防抖需要最终结果,比如输入框实时搜索(用户停止输入再搜索)、窗口 resize 结束调整后重绘。

节流需要及时反馈,比如滚动加载更多、窗口拖动、高频点击按钮。

防抖

应用防抖的场景是这样的:

第一次触发事件,事件中使用setTimeout定时器延时处理业务功能,下一次连续触发事件时,业务功能还未执行,就清除上一次setTimeout定时器,并定义新的定时器,接下来如果在延时周期内没有触发事件,则把该定时器执行完,如果在延时周期内又触发了事件,再清除上一次的定时器,然后执行新的定时器。

连续触发事件时,执行最后一次触发的事件,并且这个执行在事件里的定时器延时之后。

节流

应用节流的场景是这样的:

第一次触发事件,执行业务功能,并用特殊字段锁住业务功能,同时在setTimeout定时器中解开锁,下一次连续触发事件,无法执行业务功能,除非定时器时间到,锁解开后,业务代码才能再次被执行。

连续触发事件时,根据定时器的时间,执行每次周期内的第一次事件。

下面是我写的一个非常简单的小例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="text" oninput="inputMe()">
  <button onclick="clickMe()">点击</button>
  <script>
    // 防抖
    let timer = null;
    function inputMe() {
      if(timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(()=>{
        console.log('222'); //这里是业务代码
      },2000);
    }

    // 节流
    let flag = false;
    function clickMe() {
      if(!flag) {
        console.log('111'); //这里是业务代码
        flag = true;
        setTimeout(()=>{
          flag = false;
        },1000);
      }
    } 
  </script>
</body>
</html>

总结

日常开发中,根据业务需求选择策略——是否需要即时反馈(节流)或只需最终结果(防抖)。