前端效能最佳化---防抖與節流--02

最小生成树發表於2024-08-03

防抖(Debounce)和節流(Throttle)是兩種常用的最佳化技術,主要用於控制高頻率的事件觸發,如滾動、輸入、視窗調整大小等。本文將深入探討防抖與節流的原理、實現方法及其應用場景。

簡單場景就是:輸入框防抖,滾動節流

1. 防抖(Debounce)

防抖是一種在事件頻繁觸發時,透過延遲執行來減少事件觸發次數的技術。防抖的核心思想是:當事件被觸發時,不立即執行處理函式,而是設定一個定時器,如果在定時器未結束前再次觸發事件,則重新開始計時。這樣可以確保在一定時間內只執行一次事件處理函式。

實現原理:

function debounce(func, wait) {
    let timeout;
    return function(...args) {
        const context = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
    };
}

示例應用:

在搜尋框輸入時,實時傳送請求獲取搜尋建議。如果不進行防抖處理,每次輸入都會傳送請求,造成伺服器壓力和資源浪費。透過防抖可以最佳化這種場景:

const searchInput = document.getElementById('search');
const handleSearch = debounce((event) => {
    console.log('Fetching search results for:', event.target.value);
    // 傳送搜尋請求
}, 300);

searchInput.addEventListener('input', handleSearch);

2. 節流(Throttle)

節流是一種在事件頻繁觸發時,透過限制函式執行頻率來減少事件處理次數的技術。節流的核心思想是:在規定的時間間隔內只執行一次事件處理函式,不論期間事件觸發了多少次。

實現原理:

function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        const context = this;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

示例應用:

在頁面滾動時,實時計算滾動位置以顯示回到頂部按鈕。如果不進行節流處理,滾動事件會頻繁觸發,導致效能問題。透過節流可以最佳化這種場景:

const handleScroll = throttle(() => {
    console.log('Scroll position:', window.scrollY);
    // 處理滾動事件
}, 200);

window.addEventListener('scroll', handleScroll);

3. 防抖與節流的選擇

防抖和節流雖然都是用於控制高頻事件,但它們的應用場景有所不同:

  • 防抖:適用於頻繁觸發但只需最後一次結果的場景,如搜尋輸入、視窗大小調整等。
  • 節流:適用於持續觸發但需要定期執行的場景,如滾動事件、視窗滾動位置計算等。

4. 深入最佳化

立即執行版防抖:

有時我們希望在事件觸發時立即執行一次,然後再進行防抖控制,可以在防抖函式中新增一個立即執行選項:

function debounce(func, wait, immediate) {
    let timeout;
    return function(...args) {
        const context = this;
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            timeout = null;
            if (!immediate) func.apply(context, args);
        }, wait);
        if (callNow) func.apply(context, args);
    };
}

帶有標識的節流:

有時我們希望在節流過程中能夠獲取到當前的狀態,可以在節流函式中新增一個標識:

function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        const context = this;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

5. 綜合應用

在實際開發中,防抖與節流可以結合使用。例如在一個實時搜尋的頁面中,使用者輸入時進行防抖處理,而在結果展示時進行節流處理,以最佳化整體效能。

const searchInput = document.getElementById('search');
const resultsContainer = document.getElementById('results');

const fetchResults = debounce((query) => {
    console.log('Fetching results for:', query);
    // 模擬搜尋請求
    setTimeout(() => {
        resultsContainer.innerHTML = `Results for: ${query}`;
    }, 500);
}, 300);

const handleScroll = throttle(() => {
    console.log('Scroll position:', window.scrollY);
    // 處理滾動事件
}, 200);

searchInput.addEventListener('input', (event) => {
    fetchResults(event.target.value);
});

window.addEventListener('scroll', handleScroll);

防抖與節流是前端效能最佳化中的兩項重要技術,透過合理地應用這兩種技術,可以顯著減少高頻事件帶來的效能問題,提升使用者體驗。其他效能最佳化技術,如程式碼分割、非同步載入、懶載入等,後續介紹。

相關文章