防抖(Debounce) & 節流(Throttle)

引入

瀏覽器中某些計算和處理很是昂貴。好比當鼠標響應resize, touchmove,scroll等操做時,綁定的函數觸發的頻率會很高,若是該函數稍微複雜一些,響應速度會遠遠跟不上觸發頻率,便會出現卡頓,延遲,假死等現象。javascript

下面來看一個例子,根據輸入框輸入的數據發送ajax請求:html

<!DOCTYPE html>
<html>
<head>
    <title>普通處理</title>
</head>
<body>
    <div>
        普通處理:<input type="text" id="index"/>
    </div>
    <script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } document.querySelector('#index').addEventListener('keyup', e => { ajax(e.target.value) }) } </script>
</body>
</html>
複製代碼

普通處理結果以下:java

普通處理結果

如上圖所見,在輸入時會不斷的發送請求,很是浪費資源。爲優化性能,咱們能夠使用防抖或節流來防止函數被高頻調用。ajax

防抖Debounce

原理

在事件被觸發n秒後,再去執行回調函數。若是n秒內該事件被從新觸發,則從新計時。結果就是將頻繁觸發的事件合併爲一次,且在最後執行。瀏覽器

例如

電梯5秒後會關門開始運做,若是有人進來,等待5秒,5秒以內又有人進來,5秒等待從新計時...直至超過5秒,電梯纔開始運做。服務器

使用場景

input輸入數據時請求服務器等。函數

實現

每當事件觸發,就去重置定時器。直至最後一次事件被觸發,n秒後再去執行回調函數。性能

<!DOCTYPE html>
<html>
<head>
    <title>加入防抖</title>
</head>
<body>
    <div>
        加入防抖:<input type="text" id="debounce"/>
    </div>
    <script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function debounce (fn, delay) { return args => { clearTimeout(fn.id) fn.id = setTimeout(() => { fn.call(this, args) }, delay) } } const debounceAjax = debounce(ajax, 1000) document.querySelector('#debounce').addEventListener('keyup', e => { debounceAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼

加入防抖結果以下:優化

加入防抖結果

節流Throttle

原理

規定一個時間n,n秒內,將觸發的事件合併爲一次並執行。ui

例如

電梯等第一我的進來以後,5秒後準時運做,不等待,若5秒內還有人進來,也不重置。

使用場景

resizetouchmove移動DOM,上拉列表加載數據等。

1.定時器

<!DOCTYPE html>
<html>
<head>
    <title>加入節流-定時器</title>
</head>
<body>
    <div>
        加入節流-定時器:<input type="text" id="throttle"/>
    </div>
    <script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function throttle (fn, delay) { return args => { if (fn.id) return fn.id = setTimeout(() => { fn.call(this, args) clearTimeout(fn.id) fn.id = null }, delay) } } const throttleAjax = throttle(ajax, 1000) document.querySelector('#throttle').addEventListener('keyup', e => { throttleAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼

加入節流-定時器結果以下:

加入節流-定時器結果

2.時間戳

<!DOCTYPE html>
<html>
<head>
    <title>加入節流-時間戳</title>
</head>
<body>
    <div>
        加入節流-時間戳:<input type="text" id="throttle"/>
    </div>
    <script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function throttle (fn, delay) { let last = 0 return args => { let now = Date.now() if (now > last + delay) { fn.call(fn, args) last = now } } } const throttleAjax = throttle(ajax, 1000) document.querySelector('#throttle').addEventListener('keyup', e => { throttleAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼

加入節流-時間戳結果以下:

加入節流-時間戳結果

3.定時器 & 時間戳

<!DOCTYPE html>
<html>
<head>
    <title>加入節流-定時器 & 時間戳</title>
</head>
<body>
    <div>
        加入節流-定時器 & 時間戳:<input type="text" id="throttle"/>
    </div>
    <script> window.onload = () => { function ajax (data) { console.log(new Date().toLocaleTimeString() + ' - ' + data) } function throttle(fn, delay) { let last return args => { let now = Date.now() if (last && now < last + delay) { clearTimeout(fn.id) fn.id = setTimeout(() => { fn.call(this, args) last = now }, delay) } else { fn.call(this, args) last = now } } } const throttleAjax = throttle(ajax, 1000) document.querySelector('#throttle').addEventListener('keyup', e => { throttleAjax(e.target.value) }) } </script>
</body>
</html>
複製代碼

加入節流-定時器 & 時間戳結果以下:

加入節流-定時器 & 時間戳結果

小結

本文主要介紹了防抖與節流的實現方式。其中,防抖的核心思想是高頻操做執行結束,n秒後僅執行一次;而節流是每隔一段時間就會執行一次。

感謝閱讀,若有問題,歡迎指正。

相關文章
相關標籤/搜索