手撕代码——节流与防抖

欢迎大家来到手撕代码系列,本期介绍的是前端常见的节流与防抖的内容,包括节流与防抖的定义、它们的示例代码、它们常见的业务场景。如有错误,烦请各位大佬指正,主打一个听劝!

在开发中我们经常会遇到一些高频率事件,比如:鼠标移动,滑动窗口,键盘输入,按钮点击等等。无论是节流还是防抖,其实都是对于这种高频率事件的一种优化,如果我们的事件不需要那么高的触发频率,节流防抖是一种很好的性能优化方案。

节流

定义

节流是指在某个事件持续触发时,限制一定时间间隔只执行一次回调函数。

举个很生动的例子,就像游戏里面的普通攻击一样,无论你在一次普攻动作时间内点多少次普攻键,它都只会普攻一下。

业务场景

假设我们假设有一个按钮,点击一次就能造成页面上出现某些过渡效果,我们假设这个过渡动画为1s,此时我们不希望用户点击过快导致1s的动画还没结束就进入下一个动画,因此我们可以对这个过渡动画的回调函数进行节流处理。

示例代码

时间戳实现

以下这段节流代码是3s内只能触发一次回调函数,通过计算两个时间戳的差值来实现,当触发回调函数后又重新重置pretime,重新开始3s的节流处理。同时处理了send函数的this指向以及额外参数的问题。

注意:throttle函数会在第一次触发时就调用回调函数

html 复制代码
<body>
  <button id="btn">提交</button>
</body>

<script>
  function send(msg1,msg2) {
    console.log(msg1,msg2);
    console.log(this);
  }
  const btn = document.getElementById("btn");
  btn.addEventListener("click", throttle(send, 3000,'haha','hihi'));

  function throttle(fun, delay,...args) {
    let pretime = Date.now();
    return function () {
      if (Date.now() - pretime > delay) {
        //箭头函数,此时this就是指向btn
        fun.call(this, ...args); 
        // 如果调用成功重置pretime
        pretime = Date.now();
      }
    };
  }
</script>

定时器实现

这段代码通过定时器实现节流

注意:throttle2函数会时间到达后最后自动执行一次回调函数

html 复制代码
<body>
  <button id="btn">提交</button>
</body>

<script>
  function send(msg1,msg2) {
    console.log(msg1,msg2);
    console.log(this);
  }
  const btn = document.getElementById("btn");
  btn.addEventListener("click", throttle(send, 3000,'haha','hihi'));

  function throttle(fun, delay,...args) {
    let pretime = Date.now();
    return function () {
      if (Date.now() - pretime > delay) {
        //箭头函数,此时this就是指向btn
        fun.call(this, ...args); 
        // 如果调用成功重置pretime
        pretime = Date.now();
      }
    };
  }
</script>

防抖

定义

防抖指的是无论触发多少次事件,在事件触发最后一次后 n 秒后才执行。

就像游戏里面的回城一样,回城传送这个动作需要点击回城键几秒后才能实现,这几秒内如果我打断了回城这个动作那我就要重新开始计时。

业务场景

防抖最典型的业务场景就是搜索框了。当用户在搜索框内打字时,可能关键字还没有输入完毕,此时我们发送请求是无意义的,同时也会加重服务器的负担。于是我们通过防抖函数,设置为输入结束后0.5s才会发送请求 ,此时用户大概率输入完毕。

示例代码

定时器实现

防抖函数与上面节流函数定时器实现的不同在于每次被事件触发以后都会重置定时器进行计时。

js 复制代码
<body>
    <!-- 创建一个提交按钮 -->
    <button id="btn">提交</button> 
</body>
</html>
<script>
    function send(msg1,msg2){
        console.log(msg1,msg2,this);
        console.log('发送请求');
    }

    const btn = document.getElementById("btn");
    btn.addEventListener("click",debounce(send,1000,'hahah','ooo')) //给btn按钮绑定点击监听事件

    function debounce(fun,time,...args){
        let name
        return function(){
            if(name) clearInterval(name)
            name = setTimeout(() => {
                fun.call(this,...args)
            }, time);
        }
    }

</script>
相关推荐
孟陬12 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
BER_c12 小时前
前端权限校验最佳实践:一个健壮的柯里化工具函数
前端·javascript
兆子龙12 小时前
别再用 useState / data 管 Tabs 的 activeKey 了:和 URL 绑定才香
前端·架构
sudo_jin12 小时前
前端包管理器演进史:为什么 npm 之后,Yarn 和 pnpm 成了新宠?
前端·npm
敲敲敲敲暴你脑袋12 小时前
写个添加注释的vscode插件
javascript·typescript·visual studio code
叁两13 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
golang学习记13 小时前
GitLens 十大神技:彻底改变你在 VS Code 中的 Git 工作流
前端·后端·visual studio code
SuperEugene13 小时前
后台权限与菜单渲染:基于路由和后端返回的几种实现方式
前端·javascript·vue.js
兆子龙13 小时前
WebSocket 入门:是什么、有什么用、脚本能帮你做什么
前端·架构
csdn飘逸飘逸13 小时前
Autojs基础-全局函数与变量(globals)
javascript