在常見的瀏覽器網頁B/S架構中,用戶在網頁發送的請求很快就能發送到服務器端,
若用戶發送的請求次數過多,后端可能無法快速處理,或某些函式執行次數過多,瀏覽器可能將面臨卡死的狀況,因此防抖函式和節流函式應運而生,
防抖函式(debounce) 本質是通過setTimeout()方法延時處理函式的自定義函式:
/*
* fn [function] 需要防抖的函式
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
let timer = null //借助閉包
return function() {
if(timer){
clearTimeout(timer) //進入該分支陳述句,說明當前正在一個計時程序中,并且又觸發了相同事件,所以要取消當前的計時,重新開始計時
timer = setTimeout(fn,delay)
}else{
timer = setTimeout(fn,delay) // 進入該分支說明當前并沒有在計時,那么就開始一個計時
}
}
}
用例: debounce( submit(), 200 )
效果:如果短時間內大量觸發同一事件,只會執行一次函式,
實作:既然前面提到了計時,實作的關鍵就在于setTimeout這個函式,由于還需要一個變數來保存計時,考慮維護全域純凈,可以借助閉包來實作,
防抖函式已經處理了某些函式執行次數過多的問題,但并不完美,當用戶短時間內大量觸發事件時只會等待用戶停止觸發后的delay毫秒后才會觸發一次函式,而若用戶有以下需求:在不停執行請求函式時也能不間斷的發送一些請求,如在滑動瀏覽器滾動條時,在控制臺列印其位置,
我們知道瀏覽器滾動條的位置是連續的,若直接列印位置會使執行列印函式次數過多,導致瀏覽器卡死,而采用防抖函式時,只會當用戶松開滑鼠停下delay毫秒后才會列印一次滾動條位置,而這并不符合用戶需要實時動態地列印滾動條位置的要求,
節流函式(throttle) 可以滿足上述要求:
(不止一種實作方案,該處只是舉例,節流函式甚至可以完全不借助setTimeout,可以把狀態位換成時間戳,然后利用時間戳差值是否大于指定間隔時間來做判定,)
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
//休息時間 暫不接客
return false
}
// 作業時間,執行函式并且在間隔期內把狀態位設為無效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
不使用setTimeout的時間戳實作節流函式的方法:
function throttle(fn, delay) {
var previous = 0;
// 使用閉包回傳一個函式并且用到閉包函式外面的變數previous
return function() {
var _this = this;
var args = arguments;
var now = new Date();
if(now - previous > delay) {
fn.apply(_this, args);
previous = now;
}
}
}
// test
function testThrottle(e, content) {
console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 1000); // 節流函式
document.onmousemove = function (e) {
testThrottleFn(e, 'throttle'); // 給節流函式傳參
}
這是一種類似于控制閥門一樣定期開放的函式,當讓函式執行一次后,在某個時間段內暫時失效,過了這段時間后才再重新激活,
效果:如果短時間內大量觸發同一事件,在函式執行一次之后,該函式在指定的時間期限內不再作業,直至過了這段時間才重新生效,
在上述列印滾動條位置的案例中,將節流函式應用進去:
document.onscroll = throttle(function() { console.log('scroll事件被觸發了' + Date.now()) }, 200)
效果是在用戶不停地滑動滾動條時,每隔200毫秒就在控制臺列印滾動條的位置,這便符合用戶的需求,
總結:
防抖/節流函式在當下的應用有很多,除了上述的案例外,具體的還有如:
防抖:每次resize/scroll觸發統計事件、文本輸入的驗證(連續輸入文字發送的AJAX請求只驗證一次)
節流:谷歌搜索框/搜索聯想、高頻點擊間斷提交,表單重復提交;
等等,
即便在前端有大量框架工具的情況下,我們處理一些問題時也總是繞不開原生的JavaScript腳本,
因此要掌握牢固的基礎知識,在面對問題時積極調動邏輯,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/291669.html
標籤:其他
上一篇:Node.js基礎
