防抖和节流 原

浏览器的一些事件,如:resize,scroll,keydown,keyup,keypress,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用。会加重浏览器的负担,导致用户体验非常糟糕,不知哪个大神发明了防抖和节流,用来控制回调函数的次数。

    //函数防抖(debounce)
    function debounce(fn, wait) {
        var timeout;
         return function() {
            if (timeout) {
                clearTimeout(timeout);
            }
            timeout = setTimeout(fn, wait);
        }
    }

    function handle() {
        console.log(12)
    }
    //滚动事件
    window.addEventListener("scroll", debounce(handle, 1000))

代码解释:先执行debounce(handle, 1000)返回一个匿名函数,然后监听scroll事件,执行匿名函数,设置一个1秒后执行handle函数的定时器,由于scroll是不断触发的,如果第一次触发与第二次触发间隔1秒或者1秒多,第一次触发scroll会执行handle函数,在控制台上会打印12,如果间隔小于1秒,因为setTimeout(fn, wait)是要在1秒后执行handle 函数,小于1秒就不执行handle函数,但是timeout定时器已经不为空,第二次scroll滚动触发debounce时就执行clearTimeout(timeout),并且执行下面的代码,因为下面的代码不是放在else里面,依次类推。 总结:如果不停的触发事件,事件间隔大于设定的时间,才执行某个函数。

如果是input的情况,这时需要传递数据

  //函数节流(throttle)
    var throttle = function(func, delay) {
        console.log("hi")
        var prev = Date.now(); //返回1970 年 1 月 1日午夜与当前日期和时间之间的毫秒数。
        return function() {
            var now = Date.now();
            if (now - prev >= delay) {
                func()
                prev = Date.now()
            }
        }
    }

    function handle() {
        console.log(Math.random())
    }

    window.addEventListener("scroll", throttle(handle, 1000))

解释:当持续触发事件时,每隔一定时间(如200ms)执行一次事件处理函数 先执行throttle(handle, 1000)返回一个匿名函数,然后触发scroll事件时执行返回的匿名函数,即未滚动的时候已经执行了throttle(handle, 1000)函数

如果是input的情况(防抖)

<body>
    <div style="" class="">
        <input type="" id="unDebounce" />
    </div>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <script type="text/javascript">
    function ajax(content) {
        console.log("ajax request" + content)
    }

    function debounce(fun, delay) {
        var timeout;
        return function(args) {
            if (timeout) {
                clearTimeout(timeout)
            }
            timeout = setTimeout(function() {
                fun(args)
            }, delay)
          
        }
    }
    let inputElement = document.getElementById("unDebounce")
    let debounceAjax = debounce(ajax, 500)
    inputElement.addEventListener("keyup", function() {
        //debounceAjax(this.value)放在匿名函数里面的原因是当keyup的时候才执行,如果不放在里面会先执行此函数,导致没有值
        debounceAjax(this.value)
    })
	</script>
</body>

如果是input的情况(节流)  

<body>
    <div style="" class="">
        <input type="" id="throttle" />
    </div>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <script type="text/javascript">
    function ajax(content) {
        console.log("ajax request" + content)
    }

    function throttle(func, delay) {
        var pre = Date.now();
        var deferTimer;
        console.log("pre " + pre)
        return function(args) {
            var now = Date.now()
            console.log("now " + now)
            console.log(now - pre)
            if (now - pre >= delay) {
                func(args)
                pre = Date.now()
            } else {
                clearTimeout(deferTimer);
                deferTimer = setTimeout(function() {
                    func(args)
                    pre = Date.now()
                }, delay)

            }
        }
    }

    var throttleAjax = throttle(ajax, 2000)

    var inputc = document.getElementById('throttle')
    inputc.addEventListener('keyup', function() {
        throttleAjax(this.value)
    })
    </script>
</body>

防抖和节流的区别: 防抖是根据事件间隔是否大于设定的值来决定回调函数是否执行(取决于事件间隔,或者最后一次滚动); 节流是根据事件不停触发时时间间隔大于设定的值才执行回调函数(每隔多少秒执行一次);

公众号:前端之攻略

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券