函数节流和防抖

226 阅读1分钟

throttle

概念:触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用 适用场景:窗口调整(resize)、页面滚动(scroll)、抢购疯狂点击(movedown)

function throttle(fn, interval) {
    let last = 0;
    return function() {
        let context = this;
        let args = arguments;
        let now = new Date.getTime();
        if(now - last >= interval) {
            fn.apply(context, args);
            last = now;
        }
    }
}

debounce

在特定时间延迟内连续多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行 适用场景: 实时搜索(keyup)、拖拽(mousemove)

function debounce(fn, delay) {
    let timer = null;
    return function () {
        let context = this;
        let args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn.apply(this, args);
        }, delay);
    }
}

## 用 Throttle 来优化 Debounce

如果用户的操作十分频繁——每次都不等 debounce 设置的 delay 时间结束就进行下一次操作,于是每次 debounce 都为该用户重新生成定时器,回调函数被延迟了不计其数次。频繁的延迟会导致用户迟迟得不到响应,用户同样会产生“这个页面卡死了”的观感。

为了避免这个问题,我们需要改进:delay的时间到了,必须要给用户一个响应,也就是要调用一次执行函数。

    function throttle(fn, delay) {
        let timer = null, last  = 0;
        return function() {
            let context = this;
            let args = arguments;
            let now = new Date.getTime();
            // 确保delay的时间内至少执行一次
            if (now - last >= delay) {
                fn.apply(this, args);
                last = now;
            } else {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    last = now;
                    fn.apply(this, args);
               }, delay);
            }
        }
    }