概念了解
防抖:在事件被觸發n秒後再執行回調,如果在這n秒内又被觸發,則重新計時。
節流:規定在一個機關時間内,隻能觸發一次函數。如果這個機關時間内觸發多次函數,隻有一次生效。
js函數防抖與節流的差別:
函數防抖是某一段時間内隻執行一次,而函數節流是間隔時間執行。
個人踩坑
1、通過了解函數防抖與函數節流的概念後,使用閉包實作函數防抖和節流,沒有考慮到對于節流,如果使用者在下一次請求之前已輸入完畢,但是此時不會再進行請求,則會導緻最後輸入的文字擷取其他事件改變不發請求,即漏請求,是以需要加一個setTimeout兜底函數,且在每次準備請求的時候,設一個flag,即是否已經發送請求,如果走了正常周期發送請求,改為true,否則即為false,走setTimout,讓setTimeout比剩餘事件略長一些,優先走節流定時器請求;
2、如果是Input輸入事件,需要加入上面的逾時兜底,如果是點選事件節流,不需要加入逾時兜底;
3、如果使用箭頭函數,則不需要儲存this。
代碼實作
div>
<div>
<input type="text" id="unDebounce">
</div>
<div>
<input type="text" id="debounce">
</div>
<div>
<input type="text" id="throttle">
</div>
</div>
// 函數防抖節流
var elem1 = document.getElementById("unDebounce")
var elem2 = document.getElementById("debounce")
var elem3 = document.getElementById("throttle")
// 不防抖
function ajax1(value){
console.log("不防抖,不節流")
console.log(value)
}
elem1.addEventListener('keyup',function (e) {
ajax1(e.target.value);
})
// 防抖
function ajax2(value) {
console.log(value)
}
function debounce(func,delay){
console.log("函數防抖")
let timer = null;
return function(...args){
if(timer){
console.log("清除定時器")
clearTimeout(timer)
}
timer = setTimeout(()=>{
console.log("重新計時")
func.call(this,...args)
},delay)
}
}
let debounceFn = debounce(ajax2,1000)
elem2.addEventListener('keyup',function (e) {
debounceFn(e.target.value);
})
// // 節流
function ajax3(value){
console.log(value)
}
function throttle(func,delay){
console.log("函數節流")
let lastTime = 0;
let timer = null;
return function (...args) {
let flag = false ; // 還沒發送資料
let now = +new Date().getTime();
if(timer){
clearTimeout(timer)
}
if(now-lastTime>=delay){
console.log("目前時間大于設定時間,開始執行函數")
func.apply(this,args)
console.log("time1",new Date().getTime())
lastTime = now;
flag = true; // 發送了資料
}else{
timer = setTimeout(()=>{
if(!flag){ // 如果沒有發送資料成功,再走這個,兜底發送請求
func.apply(this,args)
console.log("time2",new Date().getTime())
}
},delay-(now-lastTime)+1000) // setTimeout多一些,優先執行周期性請求
}
}
}
let throttleFn = throttle(ajax3,5000)
elem3.addEventListener('keyup',function (e) {
throttleFn(e.target.value);
})