手撕代码——节流与防抖

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

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

节流

定义

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

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

业务场景

假设我们假设有一个按钮,点击一次就能造成页面上出现某些过渡效果,我们假设这个过渡动画为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>
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄2 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端