文章中英模式
布魯斯前端JS面試題目 - 實作節流函數優化數據請求
學習如何實作節流函數,控制高頻事件觸發頻率,優化滾動加載、頻繁API請求等前端性能問題。
文章中英模式
懶得看文章?那就來看影片吧
什麼是節流 (Throttle)?
節流是一種優化技術,用於限制函數在一段時間內的執行頻率。與防抖(Debounce)僅執行最後一次操作不同,節流確保函數在指定的時間間隔內最多執行一次。
核心原理:固定間隔時間內只執行一次函數,無論事件觸發頻率多高,效果類似於水龍頭的流量控制。
節流應用場景
- 1. 滾動事件處理(如滾動加載、固定導航欄)
- 2. 監聽resize事件調整佈局
- 3. 拖拽操作更新介面
- 4. 頻繁的資料請求或API呼叫
- 5. 實時遊戲中的按鍵響應
- 6. Canvas 繪圖操作
基本實作:節流函數 (Throttle)
以下是兩種常見的實現方式:時間戳方法和定時器方法。
方法一:時間戳實現
function throttle(func, delay = 300) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
// 檢查距離上次執行是否已經超過延遲時間
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}
方法二:定時器實現
function throttle(func, delay = 300) {
let timer = null;
return function(...args) {
// 如果沒有定時器運行中,則設置新的定時器
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, delay);
}
};
}
方法三:綜合方法(首尾調用都不丟失)
function throttle(func, delay = 300) {
let timer = null;
let lastTime = 0;
return function(...args) {
const now = Date.now();
const remaining = delay - (now - lastTime);
// 清除定時器並立即執行
if (remaining <= 0) {
if (timer) {
clearTimeout(timer);
timer = null;
}
func.apply(this, args);
lastTime = now;
} else if (!timer) {
// 設置定時器,確保最後一次操作被執行
timer = setTimeout(() => {
func.apply(this, args);
lastTime = Date.now();
timer = null;
}, remaining);
}
};
}
實際應用:節流優化資料請求
以下是一些節流函數在資料請求中的實際應用:
案例一:滾動加載資料
// 頁面滾動時加載更多數據
function loadMoreData() {
console.log('加載更多數據...');
// 計算滾動位置
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
const clientHeight = document.documentElement.clientHeight || window.innerHeight;
// 滾動到底部附近時,加載更多
if (scrollTop + clientHeight >= scrollHeight - 100) {
fetch('/api/posts?page=' + currentPage)
.then(response => response.json())
.then(data => {
// 處理數據,添加到頁面上
displayData(data);
currentPage++;
});
}
}
// 使用節流函數優化滾動事件
const throttledLoadMore = throttle(loadMoreData, 500);
window.addEventListener('scroll', throttledLoadMore);
案例二:即時搜尋建議
// 發送搜尋請求
function fetchSearchResults(query) {
console.log('搜尋:', query);
fetch(`/api/search?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(results => {
// 更新搜尋結果顯示
updateSearchResults(results);
})
.catch(error => {
console.error('搜尋錯誤:', error);
});
}
// 使用節流函數限制請求頻率
const throttledSearch = throttle(fetchSearchResults, 300);
// 綁定到輸入事件
document.querySelector('#search-input').addEventListener('input', (e) => {
const query = e.target.value.trim();
if (query.length > 2) {
throttledSearch(query);
}
});
節流與防抖比較
節流和防抖都是限制事件處理頻率的方法,但適用於不同場景:
特性 | 節流 (Throttle) | 防抖 (Debounce) |
---|---|---|
執行時機 | 固定時間內最多執行一次 | 等待指定時間後執行,期間若再觸發則重新計時 |
執行頻率 | 穩定固定的頻率 | 僅在事件停止後執行一次 |
適用場景 | 滾動加載、拖拽效果、頻繁API呼叫 | 搜尋建議、表單驗證、視窗調整大小 |
類比 | 水龍頭限流 | 電梯等待所有人進入後再啟動 |