JS防抖和節流
一.背景
我們日常開發中會經常遇到的問題,用戶的行爲會頻繁的觸發事件執行,對DOM操作、資源加載等耗費性能的處理,很可能導致界面卡頓,甚至瀏覽器的崩潰。函數防抖(debounce)和函數節流(throttle)就是爲了解決類似的需求應運而生的。
二.概念
函數防抖和函數節流都是防止某一時間頻繁觸發,但是這兩兄弟之間原理卻不一樣
函數防抖是某一段時間內只執行一次,而函數節流是間隔時間執行
函數防抖(debounce)與函數節流(throttle)都是爲了限制函數的執行頻次,以優化函數觸發頻率過高導致的響應速度跟不上觸發頻率,出現延遲,假死或卡頓的現象
1.防抖debounce
函數防抖,就是指觸發事件後在規定時間內函數只能執行一次,如果在規定時間內又觸發了事件,則會重新計算函數的執行時間
通俗的說,當我們一個動作,連續被觸發,那麼就只執行最後一次,比如我們電梯進人,電梯需要感應到沒有人了纔會自動觀門,每次進入一個,電梯就會多等幾秒鐘纔會關閉
var ipt1 = document.querySelector('.ipt1');
var comment = document.querySelector('.comment');
//沒有防抖
ipt1.onkeyup = function () {
$.ajax({
method: 'get',
url: '',
data: {
searchText: ipt1.value
},
success: function (res) {
comment.innerHTML += res;
}
});
}
這是沒有防抖的代碼,文本框每次輸入,鍵盤按下的時候,都會執行,大大的浪費了請求的資源,所以呢,我們優化一下上述代碼,使用防抖原理
// 防抖
var deferTimer;
ipt2.onkeyup = function () {
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
$.ajax({
method: 'get',
url: '',
data: {
searchText: ipt2.value
},
success: function (res) {
comment.innerHTML += res;
}
});
}, 400);
}
這樣我們就能節省請求的資源了,現在對防抖封裝一下,以便日後使用:
/*
* 防抖函數
* @delay 延遲多少毫秒
* @callback 請求網絡資源的回調函數
*/
function debounce(delay, callback) {
var deferTimer;
return function () {
//清除延時器
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
callback();
}, delay);
}
}
2.節流throttle
規定在一個單位時間內,只能觸發一次函數。如果這個單位時間內觸發多次函數,只有一次生效。
跟我們生活的一個情景很相似,進入公司裏面時,刷卡過閘機時,每個人等待幾秒後關閉,等待下一個人
//節流
var lastTime = Date.now();
ipt3.onkeyup = function () {
var nowTime = Date.now();
if (nowTime - lastTime >= 1000) {
lastTime = nowTime;
$.ajax({
method: 'get',
url: '',
data: {
searchText: ipt2.value
},
success: function (res) {
comment.innerHTML += res;
}
});
}
}
上述代碼就是採用了函數節流的原理實現,同樣,下面封裝一個節流函數
/*
* 節流函數
* @delay 延遲多少毫秒
* @callback 請求網絡資源的回調函數
*/
function throttle(delay, callback) {
var lastTime = Date.now();
return function () {
var nowTime = Date.now();
//對比時間搓,如果超過了規定時間則可以執行
if (nowTime - lastTime >= delay) {
lastTime = nowTime;
callback();
}
}
}
三.應用場景
1.防抖 debounce應用
-
search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源。
-
window觸發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其只觸發一次。
-
驗證手機號是否註冊時
2.節流throttle應用
- 鼠標不斷點擊觸發,mousedown單位時間內只觸發一次 (典型的應用:拖拽)
- 監聽滾動事件,比如是否滑到底部自動加載更多,用throttle來判斷
- 高頻點擊提交,表單重複提交
四.總結
函數節流不管事件觸發有多頻繁,都會保證在規定時間內一定會執行一次真正的事件處理函數,而函數防抖只是在最後一次事件後才觸發一次函數。
函數防抖就是法師發技能的時候要讀條,技能讀條沒完再按技能就會重新讀條。
函數節流就是射手射擊的射速,就算不停按着鼠標射擊,也只會在規定射速內射出子彈。