防抖和節流

瀏覽器的一些事件,如: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>

防抖和節流的區別: 防抖是根據事件間隔是否大於設定的值來決定回調函數是否執行(取決於事件間隔,或者最後一次滾動); 節流是根據事件不停觸發時時間間隔大於設定的值才執行回調函數(每隔多少秒執行一次);瀏覽器

公衆號:前端之攻略閉包

相關文章
相關標籤/搜索