js的防抖和节流

        在之前的学习过程中,一直碰到防抖节流这两个词,但是一直不知道是干什么用的,所以在网上搜索了很多帖子关于防抖和节流的应用场景和代码示例。在这里做一个用法的记录和个人的一些总结。

        下面这段代码是有一个div,用户鼠标放在上面会引起里面的数字自增,模拟的情况是用户会多次向后端发起请求,请求速度是非常快的。(本文章代码均引自文末的文章,侵删)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
    <script>
        let num = 1;
        let content = document.getElementById('content');

        function count() {
            content.innerHTML = num++;
        };
        content.onmousemove = count;     
    </script>
</body>
</html>

        一、防抖(debounce)

        防抖就是触发事件只能在n秒执行一次,如果n秒内再次执行,则会重新计划执行时间。

 

        1. 应用背景

  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖。比如说有时候网速不好的情况,容易向后端发送多次请求,此时就需要用到防抖。
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖。浏览器窗口时间resize触发是相当多的,可以类比平时打印鼠标位置,一瞬间可以打印几十上百条,这里也需要防抖来进行优化。
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存。csdn的发布文章功能就是定时保存草稿,应该用到的就是防抖。

        2. 代码示例

        防抖分为立即执行防抖非立即执行防抖。下面分别来看一下实现代码。

        立即执行防抖

        

立即执行大概逻辑就是,第一次触发事件,直接调用函数(立即体现在这里),然后在后面的n秒内再次调用函数都会清空计时器(防抖),必须满足大于n秒,才会重新触发事件,直接调用函数

       
    //立即执行版
    function debounce(func,delay){
        let timeout;
        return function(){
            let context = this;     //this绑定的是外层的content,不明白的可以看看闭包
            let args = arguments;

            if (timeout) clearTimeout(timeout);  //清除计时器
    
            let callNow = !timeout;  //判断是否立即执行
            timeout = setTimeout(()=>{
                timeout = null;
            },delay)      //setTimeout 如果在delay时间之内再次触发就会返回一个id
    
            if(callNow) func.apply(context,args);  //apply重新绑定作用域和参数
        }
    }

     content.onmousemove = debounce(count,1000);

         非立即执行防抖

 非立即执行的逻辑是,触发事件后,需要延时等待n秒才会调用函数(非立即),如果这n秒中再次触发事件,就会清空计时器,必须满足大于n秒,才会重新触发事件,调用函数。

 //非立即执行版
    function debounce(func,delay){
        let timeout;
        return function(){
            let context = this;     //this绑定的是外层的content,不明白的可以看看闭包
            let args = arguments;

            if (timeout) clearTimeout(timeout);  //清除计时器
      
            timeout = setTimeout(()=>{
                func.apply(context,args);  //apply重新绑定作用域和参数
            },delay)      //setTimeout 如果在delay时间之内再次触发就会返回一个id
    
        }
    }

     content.onmousemove = debounce(count,1000);

        二、 节流(throttle)

        节流就是n秒内只能多次触发只能调用一次函数。主要分为定时器版时间戳版。

 

 

        1. 应用背景

  • 滚轮事件,每隔一秒计算一次位置信息等。
  • 浏览器播放事件,每个一秒计算一次进度信息等
  • input 框实时搜索并发送请求展示下拉列表,没隔一秒发送一次请求 (也可做防抖)

        2. 代码示例

        计时器版        

function throttle(func ,delay){
    let timeout;
    return function(){
        let context = this;
        let args = arguments;
        if(!timeout){    //这里相当于开关锁,执行一次后就关锁了,必须等到delay之后,才会开锁
            timeout = setTimeout(()=>{
                timeout = null; 
                func.apply(context, delay);
            },delay)
        }
    }
}

content.onmousemove = throttle(count,1000);

        时间戳版

function throttle (func , delay){
    let prev = 0;
    return function(){
        let now = Date.now();
        let context = this;
        let args = arguments;
        if(now - prev > delay){ //这里相当于开关锁
            func.apply(context, args);
            prev = now;
        }
    }
}

content.onmousemove = throttle(count,1000);

三、总结

  • 防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout
  • 节流:控制流量,单位时间内事件只能触发一次。代码实现重在开锁关锁。

参考文章:函数防抖和节流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值