瞭解防抖debounce函式與節流throttle函式
阿新 • • 發佈:2021-02-13
技術標籤:JavaScirpt
文章目錄
作用
- 優化高頻率執行js程式碼的一種手段,js中的一些事件如瀏覽器的resize、scroll,滑鼠的mousemove、mouseover,input輸入框的keypress等事件在觸發時,會不斷地呼叫繫結在事件上的回撥函式,極大地浪費資源,降低前端效能。
- 為了優化體驗,需要對這類事件進行呼叫次數的限制。
防抖函式
在事件被觸發n秒後再執行回撥,如果在這n秒內又被觸發,則重新計時。
對於函式防抖,有以下幾種應用場景:
- 給按鈕加函式防抖防止表單多次提交。
- 對於輸入框連續輸入進行AJAX驗證時,用函式防抖能有效減少請求次數。
- 判斷
scroll
是否滑到底部,滾動事件
+函式防抖
總的來說,適合多次事件一次響應的情況
- 首先我們寫一個監聽滑鼠移動事件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title >
</head>
<body>
<script>
function testDebounce() {
console.log('test');
}
document.onmousemove = () => {
testDebounce();
}
</script>
</body>
</html>
- 最簡單的防抖函式:
var timer; // 維護同一個timer
function debounce(fn, delay) {
clearTimeout (timer);
timer = setTimeout(function(){
fn();
}, delay);
}
- 為滑鼠移動事件新增防抖函式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var timer; // 維護同一個timer
function debounce(fn, delay) {
clearTimeout(timer);
timer = setTimeout(function(){
fn();
}, delay);
}
// test
function testDebounce() {
console.log('test');
}
document.onmousemove = () => {
// testDebounce();
debounce(testDebounce, 1000);
}
</script>
</body>
</html>
-
上面例子中的debounce就是防抖函式,在document中滑鼠移動的時候,會在onmousemove最後觸發的1s後執行回撥函式testDebounce;如果我們一直在瀏覽器中移動滑鼠(比如10s),會發現會在10 + 1s後才會執行testDebounce函式(因為clearTimeout(timer)),這個就是函式防抖。
-
可以看到大大減小了onmousemove事件的呼叫次數。
-
防抖函式優化進階:
function debounce(fn, delay) {
let timer = null;
return function(...args) {
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
}
}
- 進階測試:
function debounce(fn, delay) {
let timer = null;
return function(...args) {
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
}
}
// test
function testDebounce(e, content) {
console.log(e, content);
}
var testDebounceFn = debounce(testDebounce, 1000); // 防抖函式
document.onmousemove = function (e) {
testDebounceFn(e, 'debounce'); // 給防抖函式傳參
}
節流函式
每隔一段時間,只執行一次函式。
對於函式節流,有如下幾個場景:
- 遊戲中的重新整理率
- DOM元素拖拽
- Canvas畫筆功能
總的來說,適合大量事件按時間做平均分配觸發。
- 節流函式
function throttle(fn, gapTime) {
let _lastTime = null;
return function () {
let _nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn();
_lastTime = _nowTime
}
}
}
- 測試:
let fn = ()=>{
console.log('boom')
}
setInterval(throttle(fn,1000),10)
結果是一秒打出一次boom
比較
相同點:
- 都可以通過使用 setTimeout 實現。
- 目的都是,降低迴調執行頻率。節省計算資源。
不同點:
- 函式防抖,在一段連續操作結束後,處理回撥,利用clearTimeout 和 setTimeout實現。函式節流,在一段連續操作中,每一段時間只執行一次,頻率較高的事件中使用來提高效能。
- 函式防抖關注一定時間連續觸發的事件只在最後執行一次,而函式節流側重於一段時間內只執行一次。