防抖(debounce)与节流(throttle)

120 阅读1分钟

防抖

概念
事件在 t 秒内只能执行一次,如果在 t 秒内再次触发,则在下一个 t 秒后触发,通俗来说就是只执行重复操作的最后一次
即:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时

场景
点击防抖、input-onchange

image.png

 function debounce(fn, delay = 1000) {
     let timer = null;
     return function() {
         if (timer) {
             clearTimeout(timer);
         }
         timer = setTimeout(fn, delay);
     };
 }

节流

概念
事件连续触发, 但是在 t 秒中只执行一次

场景
函数被频繁调用:window.onresize、mousemove、上传进度等各种函数被触发的频率过高的场景

image.png

 function throttle(fn, delay = 1000) {
    let executeStatus = false; // 记录函数执行状态
    return function() {
        if(executeStatus) {
            return false
        }
        executeStatus = true;
        setTimeout(() => {
            fn();
            executeStatus = false;
        }, delay)
    }
 }

扩展

分时函数

场景
比如一次性创建成百上千个节点...
解决方案
让节点创建分批进行,利用setTnterval

惰性加载函数

比如针对兼容不同浏览器的api的函数操作,把在第一次进入条件分支(浏览器嗅探的处理),函数内部重写该函数,后续调用该函数,就不再需要条件分支判断

const type = 'xxx'; // 假定一个依赖条件,并且永久不变,例如是一个UA判断
const objA = {
    funB() {
    },
};

/**js只会执行一次: 也可以将重写逻辑放到函数内部执行*/
if (type === 0) {
    objA.funB = () => {
        console.log('重写funB函数');
    };
} else if (type === 1) {
    objA.funB = () => {
        console.log('重写funB函数');
    };
} else {
    objA.funB = () => {
        console.log('重写funB函数');
    };
}

objA.funB();