深入理解节流和防抖

hwJw19 发表于 2021/06/30 21:52:06 2021/06/30
【摘要】 节流和防抖,是在前端面试的时候,有很大概率会被提到的问题,我曾经就遇到过,虽然我了解过这两个概念,在工作中其实也用到过,但是被面试官一问,还是懵了,没办法,厚着脸皮让人家给举个适用场景,我说了下解决方案。之前也的确没有写到过节流和防抖的博文,虽然网上有很多介绍他俩的文章,但我还是觉得自己总结写篇文章,会理解的更好记忆的也会更深刻一些。下面就正式开始吧~其实节流和防抖,可能单独说名词,有的朋友...

节流和防抖,是在前端面试的时候,有很大概率会被提到的问题,我曾经就遇到过,虽然我了解过这两个概念,在工作中其实也用到过,但是被面试官一问,还是懵了,没办法,厚着脸皮让人家给举个适用场景,我说了下解决方案。

之前也的确没有写到过节流和防抖的博文,虽然网上有很多介绍他俩的文章,但我还是觉得自己总结写篇文章,会理解的更好记忆的也会更深刻一些。下面就正式开始吧~

其实节流和防抖,可能单独说名词,有的朋友会恍惚一下,感觉我不清楚啊,其实在工作中,你是有用到过的,想要理解,最好先知道他俩的共同点,区别以及适用场景。

共同点:都是用于处理高频事件的,一个事件被高频率触发,一个是比较消耗浏览器性能,再一个就是它们触发的事件,如果是一个相对复杂的事情,可能第一次触发还没处理完,第二次又被触发了,显然这不是正常的情景。

区别:

字面上理解,防抖,就像我们拍照,抖动的时候拍的不清楚,会重影,什么时候不抖了,什么时候拍照,直译到js里就是,对于高频触发的时间,我们需要定义一个时间,在这个时间以内事件触发,那么我们不去调用方法,什么时候过了这个时间,事件没有被再次触发,那就可以执行方法了,简而言之,防抖只会执行一次;

而节流呢,你可以把它想象成一个水龙头,而且是拧紧一点的那种,但是还没有完全拧紧,这个水龙头会以比较缓慢的时间一滴一滴的去滴水,这其实就是节流,放到项目里,就是控制这个高频的事件发生的频率,比如每隔1秒执行一次。

结合使用场景再来理解一下。

防抖适用场景:

用户登录、发送短信验证码、调整浏览器窗口大小等。

我们具体来说一下,用户登录、获取短信验证码,这种情况一般都是按钮触发http请求,为防止用户频繁点击按钮,登录的情况下,一般在请求完成前,会先禁用按钮,等请求完成后再解禁,比如:

userLogin: function(userLoginData) {
                $.ajax({
                    url: ajaxUrlNew + '?requestType=UserLogin',
                    type: 'post',
                    dataType: 'json',
                    async: false,
                    data: userLoginData,
                    beforeSend: function() {
                        //禁用按钮
                        $('#loginbtn').attr("disabled", true);
                        $('#loginbtn').text("登录中,请稍后");
                    },
                    success: function(data) {
                        //data.Status的值为true 如果用户信息为空 提示登录失败 如果值不为空 则进行跳转
                        if (data.Status) {
                            //登录成功 页面跳转等
                            window.location.href = 'index.html';
                        } else {
                            //data.Status的值为false 判断是用户名还是密码错误 并给出对应提示 登录失败
                            layer.msg(data.Msg, {
                                icon: 5
                            });
                            $('#txtPhoneNum').val('');
                            $('#txtPW').val('');
                            return false;
                        };
                    },
                    complete: function() {
                        //按钮解禁
                        $('#loginbtn').removeAttr("disabled");
                        $('#loginbtn').text("登录");
                    },
                    error: function(err) {
                        console.log(err);
                    }
                });
            }

而获取短信验证码的需求,一般情况是请求前设置一个120s或者60s的倒计时,等倒计时结束后,才会允许用户再次请求,示例代码如下:

getRandomPassword: function() {
                var getrandomcodeBtn = $("#getrandomcode");
                getrandomcodeBtn.click(function() {
                    $.ajax({
                        url: ajaxUrlNew + '?requestType=GetPasswordService',
                        type: 'post',
                        dataType: 'json',
                        data: {
                            'phonenumber': window.sessionStorage.phoneNum
                        },
                        success: function(data) {
                            if (data.Status) {
                                layer.alert('随机验证码已发送,请注意查收', {
                                    skin: 'mybtn-class'
                                });
                                setTime = setInterval(function() {
                                    if (time <= 0) {
                                        clearInterval(setTime);
                                        $("#getrandomcode").removeAttr("disabled");
                                        $("#getrandomcode").val("获取验证码");
                                        return;
                                    }
                                    time--;
                                    $("#getrandomcode").val(time + "s后重新获取");
                                    $("#getrandomcode").attr("disabled", "true");
                                }, 1000);
                            } else {
                                layer.alert(data.Msg, {
                                    skin: 'mybtn-class'
                                });
                            }
                        },
                        error: function(err) {
                            console.log(err);
                        }
                    });
                });
            },

最后再举一个调整浏览器大小的例子:

function debounce(operate, delay) {
    let time = null;
    let timer = null;
    let newTime = null;
    function task() {
        newTime = +new Date()
        if(newTime - time < delay){
            timer = setTimeout(task, delay)
        }else {
            operate()
            timer = null
        }
        time = newTime
    }
    return function () {
        // 更新时间戳
        time = +new Date()
        if(!timer){
            timer = setTimeout(task, delay)
        }
    }
}
//打印可视区域宽度
function printWidth() {
    console.log(window.document.body.clientWidth)
}

//监听resize事件
window.addEventListener('resize', debounce(printWidth, 500), false)

节流使用场景:

scroll事件、input输入实时搜索事件等。

scroll事件,比如我们有这么一个需求,当滚动高度大于多少时,我们载入某个动画,如果我们不做节流,那scroll事件会频繁触发,但是如果们限制200ms才触发一次,然后再去对比是否符合要求呢?是不是就好很多?

function throttle(func, wait, mustRun) {
    var timeout,
        startTime = new Date();
 
    return function() {
        var context = this,
            args = arguments,
            curTime = new Date();
 
        clearTimeout(timeout);
        if(curTime - startTime >= mustRun){
            func.apply(context,args);
            startTime = curTime;
        }else{
            timeout = setTimeout(func, wait);
        }
    };
};

function realFunc(){
    console.log("Success");
}

window.addEventListener('scroll',throttle(realFunc,500,1000));

这里借用了一个别人的例子,谢谢~

对于input输入实时搜索事件,怎么去做节流处理呢,其实也是一样的,我们可以监听keyup事件,不过是每隔一段时间取监听一下。

节流和防抖就简单说了一下下,有什么不到位的地方,希望看到的朋友指出来,我积极整改~拜拜~

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。