函数节流与函数去抖

问题由来:

在项目应用PeoplePicker控件的时候突然联想到一个问题,在输入人名时不停的向后台发请求,取到数据库里面的数据。我们都知道频繁的通信会导致页面效率降低。可不可以设置个间隔,每次这个间隔通信一次而不是每次输入一个字符就通信一次呢。其实这里还有很多场景,比如resize事件,scroll事件。都会让一个回调函数不停的执行。页面操作成本是非常高的,如果不停的执行页面效率会打打折损。于是产生了两种解决方案:函数节流、函数去抖。

函数节流:

频繁的调用一个函数,我们可以添加一些限制,可以缓解频繁调用,我们可以设置个时间间隔,每次到时间调用一次。

代码:

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
</head>

<body>
    <input id="search" type="text" name="search">
    <script>
        function queryData(text) {
            console.log(text);
        }
        var input = document.getElementById("search");
        var handler = throttle(queryData, 1000);
        input.addEventListener("keyup", function (event) {
            handler(this.value);
        });
        function throttle(fn, delay) {
            var self = this,
                lastTime = 0,
                timer;
            return function (value) {
                var now = new Date().getTime();
                if (now - lastTime <= delay) {
                    return;
                }
                lastTime = now;
                clearTimeout(timer);
                timer = setTimeout(function () {
                    timeout = null;
                    fn.apply(self, [value]);
                }, delay)
            }
        }
    </script>
</body>

</html>

思路:利用闭包函数throttle保存timer以及lastTime,如果两次的调用时间间隔小于设置的规定时间,就不去调用目标函数,如果大于这个时间间隔,就去设置一个timer,然后执行这个函数。这样做的目的可以达到频繁调用函数,但是需要在一段时间才回去执行该函数,这种方式就叫做函数节流。

效果:

一直不停的输入,没1秒会打一次log。

函数去抖:

去抖可以理解成为是节流的一种情况,在一个条件内函数一直不执行,直到调出该条件。

代码:

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
</head>

<body>
    <input id="search" type="text" name="search">
    <script>
        function queryData(text) {
            console.log(text);
        }
        var input = document.getElementById("search");
        var handler = debounce(queryData, 5000);
        input.addEventListener("keyup", function (event) {
            handler(this.value);
        });
        function debounce(fn, delay) {
            var timer,
                self = this;
            return function (value) {
                clearTimeout(timer);
                timer = setTimeout(function () {
                    timer = null;
                    fn.apply(self, [value]);
                }, delay);
            };
        }
    </script>
</body>

</html>

思路:函数调用n秒后才会执行,如果函数在n秒内被调用的话,则函数不执行,重新计算执行时间。

效果:

不停的输入不会打出log,停止输入打出log。

总结:函数节流在一定程度上可以优化页面效率,减少没必要的dom渲染以及http请求,更重要的是对js可以有一个更深入的理解。

posted @ 2019-01-29 17:55  漠然0408丶  阅读(239)  评论(1编辑  收藏  举报