說到「函數(shù)防抖」和「函數(shù)節(jié)流」,兩者其實概念比較相似。
1.「函數(shù)防抖」(debounce)
通俗來說乘粒,就是把「多個信號」轉(zhuǎn)化為「單個信號」,在Javascript中伤塌,如果一個事件頻繁發(fā)生灯萍,事件在觸發(fā)后過一段事件才執(zhí)行,但是如果在這一段時間內(nèi)每聪,我們又觸發(fā)了這個事件旦棉,則會重新計時。
應(yīng)用場景:表單驗證或者提交
我們回顧下在提交表單中药薯,如果我們填好信息后绑洛,點擊「提交」按鈕,就應(yīng)該發(fā)送請求給后端了童本,但是真屯。。穷娱。绑蔫。运沦。如果你所謂的“手抖”了一下,一不小心點了10下或者更多下呢配深?那是不是就要發(fā)送很多個請求了茶袒?為了從技術(shù)上防止這種情況的出現(xiàn),于是乎有了「函數(shù)防抖」凉馆。
實現(xiàn)思路:
我們將目標(biāo)方法包裝進(jìn)setTimeout中薪寓,這個方法是一個事件的回調(diào)函數(shù),如果一定時間內(nèi)澜共,這個事件不停地被觸發(fā)向叉,那么這個回調(diào)函數(shù)就一直不被執(zhí)行,我們是通過clearTimeout來消除這個setTimeout嗦董,這樣我們就可以把一定時間內(nèi)的連續(xù)事件刪除母谎,等到過了一定時間時間,且這個時間內(nèi)不再有事件觸發(fā)京革,我們就執(zhí)行這個回調(diào)函數(shù)奇唤。
代碼(表單驗證例子):
// html代碼:<input id="input" type="text">
input.oninput = debounce(fn);
// 目標(biāo)方法
function fn() {
console.log('用戶輸入了');
}
function debounce(callback, interval = 1000) { //默認(rèn)這個「一定時間」為1秒
let timeId = null;
return function() {
if(timeId) {
clearTimeout(timeId);
}
timeId = setTimeout(() => {
callback();
}, interval)
}
}
說明:上述代碼,我們在輸入框中如果只輸入1次匹摇,過了1秒后就會log出“用戶輸入”了咬扇。但是如果我們連續(xù)輸入,就算過了1秒也沒有l(wèi)og出“用戶輸入”廊勃,直到停止輸入1秒后懈贺,才會出現(xiàn)。這就大大減少了我們不必要的請求坡垫,節(jié)約資源梭灿,提升用戶體驗。
2.「函數(shù)節(jié)流」(throttle)
為啥說兩者相似呢冰悠,都是為了避免資源浪費(fèi)堡妒,只不過兩者有些區(qū)別,上述「函數(shù)防抖」是等待用戶不再觸發(fā)事件一定時間后執(zhí)行回調(diào)函數(shù)溉卓,而「函數(shù)節(jié)流」是一定事件內(nèi)如果多次觸發(fā)事件只執(zhí)行一次回調(diào)函數(shù)皮迟。(如果事件一直觸發(fā)就相當(dāng)于每隔一定時間執(zhí)行一次回調(diào))
打個比方:
一個外賣小哥,在從商家拿外賣送到A地的诵,如果他拿到后立即送往A地万栅,送到一半佑钾,發(fā)現(xiàn)該商家又有一單外賣同樣送到A地西疤,你說他是先把第一單送完,還是先去取第二單然后一起送到A地休溶?聽起來是不是很坑代赁。但是如果我們這樣規(guī)劃扰她,我們?nèi)×说谝粏危覀冊谏碳夷堑?分鐘芭碍,看看還有沒有新的訂單(多次事件觸發(fā))徒役,如果有則一起接下,5分鐘后管他還有沒有新的訂單窖壕,都要去送了(不然就要過時被投訴啦S俏稹!U胺怼T)
應(yīng)用場景:
- DOM元素拖拽
- 判斷scroll是否到底
代碼(以scroll為例):
window.onscroll = throttle(fn);
function fn() {
// 目標(biāo)函數(shù):主要是判斷是否到底部了
let range = document.body.clientHeight - window.innerHeight - window.scrollY;
if(range <= 0) {
console.log('到底了呀!');
}
}
function throttle(callback, interval = 300) {
// 默認(rèn)每300毫秒來判斷是否到底了
let run = true;
return function() {
if(!run) return;
run = false;
setTimeout(() => {
callback();
run = true;
}, interval);
};
}
此時你會發(fā)現(xiàn)雖然都是多次觸發(fā)事件速勇,只執(zhí)行一次晌砾。「函數(shù)防抖」是等到用戶不觸發(fā)事件后才執(zhí)行一次回調(diào)函數(shù)烦磁,而「函數(shù)節(jié)流」是過了一定時間养匈,無論是否還有事件觸發(fā),都要先執(zhí)行一次回調(diào)函數(shù)都伪。
參考:
1.https://zhuanlan.zhihu.com/p/57006134
2.https://zhuanlan.zhihu.com/p/38313717