本文由小芭樂發表
首先舉一個例子:javascript
模擬在輸入框輸入後作ajax查詢請求,沒有加入防抖和節流的效果,這裏附上完整可執行代碼:css
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>沒有防抖</title> <style type="text/css"></style> <script type="text/javascript"> window.onload = function () { //模擬ajax請求 function ajax(content) { console.log('ajax request ' + content) } let inputNormal = document.getElementById('normal'); inputNormal.addEventListener('keyup', function (e) { ajax(e.target.value) }) } </script> </head> <body> <div> 1.沒有防抖的輸入: <input type="text" name="normal" id="normal"> </div> </body> </html>
效果:在輸入框裏輸入一個,就會觸發一次「ajax請求」(此處是console)。html
沒有防抖和節流java
缺點:浪費請求資源,能夠加入防抖和節流來優化一下。ajax
本文會分別介紹什麼是防抖和節流,它們的應用場景,和實現方式。防抖和節流都是爲了解決短期內大量觸發某函數而致使的性能問題,好比觸發頻率太高致使的響應速度跟不上觸發頻率,出現延遲,假死或卡頓的現象。但兩者應對的業務需求不同,因此實現的原理也不同,下面具體來看看吧。瀏覽器
在事件被觸發n秒後再執行回調函數,若是在這n秒內又被觸發,則從新計時。app
(1) 用戶在輸入框中連續輸入一串字符後,只會在輸入完後去執行最後一次的查詢ajax請求,這樣能夠有效減小請求次數,節約請求資源;函數
(2) window的resize、scroll事件,不斷地調整瀏覽器的窗口大小、或者滾動時會觸發對應事件,防抖讓其只觸發一次;性能
仍是上述列子,這裏加入防抖來優化一下,完整代碼以下:優化
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>加入防抖</title> <style type="text/css"></style> <script type="text/javascript"> window.onload = function () { //模擬ajax請求 function ajax(content) { console.log('ajax request ' + content) } function debounce(fun, delay) { return function (args) { //獲取函數的做用域和變量 let that = this let _args = args //每次事件被觸發,都會清除當前的timeer,而後重寫設置超時調用 clearTimeout(fun.id) fun.id = setTimeout(function () { fun.call(that, _args) }, delay) } } let inputDebounce = document.getElementById('debounce') let debounceAjax = debounce(ajax, 500) inputDebounce.addEventListener('keyup', function (e) { debounceAjax(e.target.value) }) } </script> </head> <body> <div> 2.加入防抖後的輸入: <input type="text" name="debounce" id="debounce"> </div> </body> </html>
代碼說明:
1.每一次事件被觸發,都會清除當前的 timer 而後從新設置超時調用,即從新計時。 這就會致使每一次高頻事件都會取消前一次的超時調用,致使事件處理程序不能被觸發;
2.只有當高頻事件中止,最後一次事件觸發的超時調用才能在delay時間後執行;
效果:
加入防抖後,當持續在輸入框裏輸入時,並不會發送請求,只有當在指定時間間隔內沒有再輸入時,纔會發送請求。若是先中止輸入,可是在指定間隔內又輸入,會從新觸發計時。
加入防抖
規定一個單位時間,在這個單位時間內,只能有一次觸發事件的回調函數執行,若是在同一個單位時間內某事件被觸發屢次,只有一次能生效。
(1)鼠標接二連三地觸發某事件(如點擊),只在單位時間內只觸發一次;
(2)在頁面的無限加載場景下,須要用戶在滾動頁面時,每隔一段時間發一次 ajax 請求,而不是在用戶停下滾動頁面操做時纔去請求數據;
(3)監聽滾動事件,好比是否滑到底部自動加載更多,用throttle來判斷;
仍是上述列子,這裏加入節流來優化一下,完整代碼以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>加入節流</title> <style type="text/css"></style> <script type="text/javascript"> window.onload = function () { //模擬ajax請求 function ajax(content) { console.log('ajax request ' + content) } function throttle(fun, delay) { let last, deferTimer return function (args) { let that = this; let _args = arguments; let now = +new Date(); if (last && now < last + delay) { clearTimeout(deferTimer); deferTimer = setTimeout(function () { last = now; fun.apply(that, _args); }, delay) } else { last = now; fun.apply(that, _args); } } } let throttleAjax = throttle(ajax, 1000) let inputThrottle = document.getElementById('throttle') inputThrottle.addEventListener('keyup', function (e) { throttleAjax(e.target.value) }) } </script> </head> <body> <div> 3.加入節流後的輸入: <input type="text" name="throttle" id="throttle"> </div> </body> </html>
效果:實驗可發如今持續輸入時,會安裝代碼中的設定,每1秒執行一次ajax請求
加入節流
總結下防抖和節流的區別:
-- 效果:
函數防抖是某一段時間內只執行一次;而函數節流是間隔時間執行,無論事件觸發有多頻繁,都會保證在規定時間內必定會執行一次真正的事件處理函數。
-- 原理:
防抖是維護一個計時器,規定在delay時間後觸發函數,可是在delay時間內再次觸發的話,都會清除當前的 timer 而後從新設置超時調用,即從新計時。這樣一來,只有最後一次操做能被觸發。
節流是經過判斷是否到達必定時間來觸發函數,若沒到規定時間則使用計時器延後,而下一次事件則會從新設定計時器。
若有問題,歡迎指正。
此文已由做者受權騰訊雲+社區發佈,更多原文請點擊
搜索關注公衆號「雲加社區」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!