防抖和节流

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

//函数防抖(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里面,依次类推。
总结:若是不停的触发事件,事件间隔大于设定的时间,才执行某个函数。html

若是是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)函数java

若是是input的状况(防抖)jquery

<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>

上面是用的闭包避免污染全局变量,用全局变量的写法更简单些ajax

<script type="text/javascript">
	function handle(content){
	  console.log("input " + content);
	}
	var timeout;
	function debounce(value,handle,wait){
	    if(timeout){
		   clearTimeout(timeout)
		}
		timeout = setTimeout(function(){
		   handle(value)
		},wait)
	}
	var inputElement = document.getElementById("unDebounce");

	inputElement.addEventListener("input",function(){
	   debounce(this.value,handle,500)
	})
</script>

若是是input的状况(节流)  bootstrap

<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>

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

公众号:前端之攻略闭包

相关文章
相关标签/搜索