防抖和节流

124 阅读1分钟

debounce 防抖

概述

事件在一段时间内连续被触发,换句话,如果每次触发的时间间隔小于delay,事件的处理不会执行。【多次操作变成一次】

实现

有两种情况

  • 用户触发事件,就立即执行,后面如果用户连续(每次触发时间小于dealy)触发,后续都不会再执行事件处理
  • 用户触发事件,如果距离上次触发事件时间超过delay,则执行事件处理
function debounce(fn, delay, immediate) {
    let timer = null;
    return (...arg) => {
        if(timer) {
            clearTimeout(timer);
        }
        if(immediate) {
            const canDo = !timer;
            timer = setTimeout(() =< {
                clearTimeout(timer);
                timer = null;
            }, delay);
            if(canDo) {
               fn.call(this, ...arg); 
            }
        }
        else {
           timer = setTimeout(() => {
                fn.call(this, ...arg);
                clearTimeout(timer);
                timer = null;
            }, delay);
        }
        
    }
}

应用场景

根据用户输入,实时搜索 在这种场景下,如果用户输入输入就触发搜索是不合理,我们只需要判断用户是输入完成(例如用户间隔500ms,没有再输入内容,判断输入完成),此时再出发搜索可以了。

window的resize 我们在使用echart时,如果窗口变化,我们是需要resize画布的,用户不断改变可视区域大小,我们其实并不需要每监听到window的resize就改变画布,只需要在最后一次再进行resize画布就行。

throttle 节流

概述

节约资源,用户不断触发事件,如果距离上次事件执行超过delay,这再执行一次事件处理 【一定时间内只调用一次】

实现

function throttle(fn, delay, immedate = true) {
    let pre = 0;
    let timer = null;
    return (...arg) => {
        const nowTime = new Date().getTime();
         if(pre + delay <= nowTime) {
             if(immedate) {
                pre = nowTime;
                fn.call(this, ...arg);
             }
             else {
                 timer = setTimeout(() => {
                     fn.call(this, ...arg);
                     clearTimeout(timer);
                     timer = null;
                 }, delay);
             }
        }        
    }
}

应用

用户点击按钮
用户不断点击按钮,如果在一段时间内,事件处理已经执行过一次了,我们就无需在执行