函数的防抖与节流

271 阅读2分钟

函数的防抖与节流目的都是在于减少事件调用频率

防抖场景:搜索场景,待用户停顿进行检测。

节流场景:验证码场景,60秒内不可以再次点击。

防抖与节流的区别

在多次连续执行中,防抖是执行最后一次,节流是执行第一次。比如上面我们提到的搜索就是检测用户最后输入值,验证码就是用户的第一次点击。

防抖

在前面的事件还没有执行完毕,又有了新的事件,那么取消前面的事件,执行新的事件。

var debounce = (fn, wait) => {
    let timer = null
    
    return (...value) => {
        // 如果前面有待执行的timer,清除timer
        if(timer) clearTimeout(timer)

        // 构建最新的timer,放入执行队列
        timer = setTimeout(()=>{
            fn(value)
        }, wait)        
    }
}

防抖升级:我们知道按照上面的话,我们在第一次输入的时候就要进行等待,这是没有必要的也影响到用户体验。 可以优化成:用户首次输入,执行不用等待->继续输入,进入防抖->抖动结束返回第一步


var debounce = (fn, wait) => {
  let timer;
  let first = true;

  return (...value) => {
    if (first) {
      first = false;
      return fn(value);
    }

    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      fn(value);
      first = true;
    }, wait);
  };
};

let con = (...val) => console.log(...val);
let conPlus = debounce(con, 2000);

conPlus("frist");
conPlus("second");
conPlus("last");

节流

在前面的事件没有执行完毕,状态固定为不可执行,待执行完毕后更新状态。

var throttle = (fn, wait) => {
    let canRun = true
    
    return (...value) => {
        // 检测状态,锁住状态则不可二次执行
        if(canRun === false){
            return 
        }
        
        /*
         * 可执行部分
         */
        
        // 更改状态为不可执行
        canRun = false
        
        // 等待函数执行完毕
        setTimeout(() => {
            fn(value)
            // 执行完毕后修改状态为可执行状态
            canRun = true
        }, wait)
    }
}

看完上面的代码,节流是不是很像厕所检修,检修员进去先在门口树一块“不可用的”警示牌,修好之后把牌子拿走。