【前端】防抖和節流

一、防抖

防抖函數的作用

防抖函數的作用就是控制函數在一定時間內的執行次數。防抖意味着 N 秒內函數只會被執行一次,如果 N 秒內再次被觸發,則 重新 計算延遲時間。

防抖函數的實現

  • 事件第一次觸發時,timeout 是 null,調用 later(),若 immediate 爲true,那麼立即調用 func.apply(this, params);如果 immediate 爲 false,那麼過 wait 之後,調用 func.apply(this, params)。
  • 事件第二次觸發時,如果 timeout 已經重置爲 null (即 setTimeout 的倒計時結束),那麼流程與第一次觸發時一樣,若 timeout 不爲 null (即 setTimeout 的倒計時未結束),那麼清空定時器,重新開始計時。
function debounce(func, wait, immediate = true) {
    let timeout, result;
    // 延遲執行函數
    const later = (context, args) => setTimeout(() => {
        timeout = null;// 倒計時結束
        if (!immediate) {
            // 執行回調
            result = func.apply(context, args);
            context = args = null;
        }
    }, wait);
    let debounced = function (...params) {
        if (!timeout) {
            timeout = later(this, params);
            if (immediate) {
                // 立即執行
                result = func.apply(this, params);
            }
        } else {
            clearTimeout(timeout);
            // 函數在每個等待時延的結束被調用
            timeout = later(this, params);
        }
        return result;
    }
    // 提供在外部清空定時器的方法
    debounced.cancel = function () {
        clearTimeout(timeout);
        timeout = null;
    };
    return debounced;
};

immediate 爲 true 時,表示函數在每個等待時延的開始被調用。immediate 爲 false 時,表示函數在每個等待時延的結束被調用。

防抖的應用場景

  1. 搜索框輸入查詢,如果用戶一直在輸入中,沒有必要不停地調用去請求服務端接口,等用戶停止輸入的時候,再調用,設置一個合適的時間間隔,有效減輕服務端壓力。

  2. 表單驗證。

  3. 按鈕提交事件。

  4. 瀏覽器窗口縮放,resize 事件 (如窗口停止改變大小之後重新計算佈局) 等。

二、節流

節流函數的作用

節流函數的作用是規定一個單位時間,在這個單位時間內最多隻能觸發一次函數執行,如果這個單位時間內多次觸發函數,只能有一次生效。

節流函數的實現

function throttle(func, wait, options = {}) {
    var timeout, context, args, result;
    var previous = 0;
    var later = function () {
        previous = options.leading === false ? 0 : (Date.now() || new Date().getTime());
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };

    var throttled = function () {
        var now = Date.now() || new Date().getTime();
        if (!previous && options.leading === false) previous = now;
        //remaining 爲距離下次執行 func 的時間
        //remaining > wait,表示客戶端系統時間被調整過
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        //remaining 小於等於 0,表示事件觸發的間隔時間大於設置的 wait
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                // 清空定時器
                clearTimeout(timeout);
                timeout = null;
            }
            // 重置 previous
            previous = now;
            // 執行函數
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };

    throttled.cancel = function () {
        clearTimeout(timeout);
        previous = 0;
        timeout = context = args = null;
    };

    return throttled;
}

禁用第一次首先執行,傳遞 {leading: false} ;想禁用最後一次執行,傳遞 {trailing: false}。

節流的應用場景

  1. 按鈕點擊事件。

  2. 拖拽事件。

  3. onScoll。

  4. 計算鼠標移動的距離 (mousemove)。

轉載自:《前端之巔》微信公衆號

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章