美文网首页
函数防抖

函数防抖

作者: jesse28 | 来源:发表于2021-03-29 15:49 被阅读0次

    一、函数防抖

    定义
    在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时;典型的案例就是输入搜索:输入结束后n秒才进行搜索请求,n秒内又输入的内容,就重新计时。

    实现原理
    函数防抖的基本思想是设置一个定时器,在指定时间间隔内运行代码时清楚上一次的定时器,并设置另一个定时器,知道函数请求停止并超过时间间隔才会执行。

    使用场景
    文本框输入搜索(连续输入时避免多次请求接口)

    防抖、节流函数主要是用来限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟、假死或卡顿的现象的。
    比如我在项目中遇到过输入查询的功能,在搜索框中输入文字调用查询接口搜索,返回与搜索框匹配的内容。

    1.封装防抖函数

        <script>
            /**
            函数防抖=>比如我们在我登录的时候很多人点击多次登录造成多次调用接口,这个时候我们只需要在登录上面做防抖,那么只会在定时器时间后最后一次触发
            */
            export function debounce(fn, delay) {
                var timer = 0;
                return function () {
                    var _this = this;//这后面的this表示谁触发了这个事件就表示谁,这个this是真的this,不然后面那个定时器里面的函数this指的是window,到时候不对
                    clearTimeout(timer); //假设这边用的是onClick事件触发===在我多次点击的时候都清楚掉定时器,就要就可以防止我迅速点击第二次触发的事件,因为被我clear掉。
                    timer = setTimeout(function () {         //注意:第一次是会执行的,因为setTimeout执行完后才会生成timer,只有timer一样清掉才不会执行。
                        fn.call(_this, arguments);
                    }, delay)
                }
            }
    
        </script>
    

    下面引用地址:https://juejin.cn/post/6844903743247368206
    防抖、节流函数主要是用来限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟、假死或卡顿的现象的。
    比如我在项目中遇到过输入查询的功能,在搜索框中输入文字调用查询接口搜索,返回与搜索框匹配的内容。

    先来一个基础的写法:

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    </head>
    <body>
        <input type="text" class="search" placeholder="搜索...">
        <script type="text/javascript">
            $("body").on("keyup", ".search", function() {  //输入时调用searchFunc函数
                searchFunc();
            })
            var searchFunc = function() {
                console.log('请求接口返回搜索内容。。。');
            }
        </script>
    </body>
    </html>
    
    

    这是这个搜索功能实现的雏形,但是运行起来会发现,只要我不断的输入,它就会不断地调用searchFunc 方法去请求接口,就是说我输入10次就会请求10次。这想想真是很糟糕透了,怎么优化这个问题呢?

    接下来就要用到防抖思想了。

    防抖函数代码实现

    (用本例解释)防抖其实就是加上一个定时器,规定它延迟一定的时间再去请求接口。

    <!DOCTYPE html>
    <html>
    <head>
        <title>防抖实现搜索</title>
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    </head>
    <body>
        <input type="text" class="search" placeholder="搜索...">
        <script type="text/javascript">
            $("body").on("keyup", ".search", function() {
                searchFunc();
            })
        var timer = null;
        var searchFunc = function() {
            timer && clearTimeout(timer);
            timer = setTimeout(function() {
                console.log('请求接口返回搜索内容。。。');
            }, 5000);
        }
        </script>
    </body>
    </html>
    

    加上了定时器之后,再运行看看,它不会再是输入多少次就请求多少次了。

    而是延时5秒之后再去做一次请求。

    需要注意的是:在这个5秒钟的时间里,你不断的输入,定时器会不断的被清除再重新设置一个。举个例子:你第一秒的时候第一次输入内容,那它开始设置一个定时器并且延时5秒钟,等到第四秒钟的时候你再次输入内容,此时程序是先把你之前设置的定时器先清除再给你重新设置一个新的定时器,这个定时器又延时5秒钟。也就是说这个定时器以你这5秒钟时间内最后一次输入的为准。

    这样就解决了频繁请求的问题。

    2.在vue项目中是如何使用的。参考链接:https://www.jianshu.com/p/a77551c3bc3f

    1.我们可以在公共方法中写入这两个函数,暴露出来

    // 防抖
    export function _debounce(fn, delay) {
     
        var delay = delay || 200;
        var timer;
        return function () {
            var th = this;
            var args = arguments;
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function () {
                timer = null;
                fn.apply(th, args);
            }, delay);
        };
    }
    // 节流
    export function _throttle(fn, interval) {
        var last;
        var timer;
        var interval = interval || 200;
        return function () {
            var th = this;
            var args = arguments;
            var now = +new Date();
            if (last && now - last < interval) {
                clearTimeout(timer);
                timer = setTimeout(function () {
                    last = now;
                    fn.apply(th, args);
                }, interval);
            } else {
                last = now;
                fn.apply(th, args);
            }
        }
    }
    

    2.在需要使用的组件引入

    import { _debounce } from "@/utils/gloal";
    

    3.在 methods 中使用

     methods: {
       // 改变场数
       changefield: _debounce(function(_type, index, item) {
           // do something ...
       }, 100)
    

    另外,我们还可以使用函数节流来优化这个问题。

    二、节流函数代码实现

    (用本例解释)给定一个间隔时间,计算一个等待时间,当等待时间大于间隔时间,则再去请求接口

    <!DOCTYPE html>
    <html>
    <head>
        <title>节流实现搜索</title>
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    </head>
    <body>
        <input type="text" class="search" placeholder="搜索...">
        <script type="text/javascript">
            $("body").on("keyup", ".search", function() {
                searchFunc(5000);
            })
            var lastTime = null, nowTime = null;
            var searchFunc = function(gapTime) {
                nowTime = new Date().getTime();
                if(nowTime - lastTime > gapTime || !lastTime) {
                    console.log('请求接口返回搜索内容。。。');
                    lastTime = nowTime;
                }
            }
        </script>
    </body>
    </html>
    
    

    从代码可以看出来就是比较当前时间和 lastTime 的差值,当差值大于gapTime的时候就去调用接口。

    函数节流的思想在本例来的体现:就是给定一个时间gapTime(比如5秒钟)代表每隔5秒钟请求一次接口搜索。不管你怎么输入,我都是按部就班的每隔5秒钟请求一次。

    函数节流详解

    相比于防抖,节流就是在让函数在特定的时间内只执行一次

    <script>
            var canRun = true;  //设定一个开关,刚进来的时候我们执行定时器输出console内容,当还没到达1s我们在onscroll时我们的canRun是false,当1s结束后  canRun = true;这个时候才能再次进入定时器
            window.onscroll = function () {
                if (!canRun) {
                    return;
                }
                canRun = false;
                setTimeout(function () {
                    console.log("函数节流")
                    canRun = true;
                }, 1000)
            }
    
        </script>
    

    案例
    1.比如:搜索框绑定 keyoress 事件、 假设我想查询“ windows phone” ,它包含 13 个字符,而我输入完成只花了 1 秒钟,那么在这 1 秒内,调用了 13 次查询方法。这是一件非常恐怖的事情,那么更好的方法是,我们希望用户已经输入完成,或者正在等待提示(也许他懒得再输入后面的内容)的时候,再查询匹配关键字。

    image.png

    2.比如:模拟百度搜索框,实现输入关键词的同时下拉菜单中的相关信息改变
    这个就没有必要每 10ms 执行一次搜索,也并不能等到用户输入结束之后才提示,此时就需要使用函数节流,间隔固定的时间下拉菜单的提示信息更新一次


    image.png

    相关文章

      网友评论

          本文标题:函数防抖

          本文链接:https://www.haomeiwen.com/subject/jtovhltx.html