防抖debounce和节流throttle 函数实现

130 阅读2分钟

1.防抖deboune

防抖第一次不是立即执行,都是延后执行。只要定时器还在,一直调用会一直取消重新创建定时。直到定时正常结束执行方法。(当然也可以使用immediate参数让方法先执行)

等一等,别着急,如果一直有新操作,那就一直推迟执行。

//防抖函数
function debounce(fn,delay) { 
    let timeId;
    return (...args) => {
        if (timeId) {
            console.log("取消之前正在执行的函数")
            clearTimeout(timeId)
        }
         timeId = setTimeout(() => { 
            fn.apply(this,args)//执行原来定义的函数+ 参数
            clearTimeout(timeId)
        },delay)
    }
} 

function hello(info) {
   console.log("hello jason",info)
}
//获取定义的防抖函数
const testFn = debounce(hello,100)
testFn("11");
testFn("22"); 
testFn("33"); 

支持先执行immediate参数版本

function debounce(func, delay,immediate) {
    let timer =null;
    return function() {
        const callNow = immediate && !timer; // 是否立即执行,每次判断上一次的timer 是否还存在
          if(callNow) {
            func.apply(this, arguments)
        }
        if(timer) {
            clearTimeout(timer);
        }
      
        timer = setTimeout(() => {
             if(!immediate) {
             func.apply(this, arguments)
            }
        }, delay);
    }
}
const fn1 = debounce((msg) => {console.log(msg)}, 1000,false) 
fn1('11')
fn1('22')
fn1('33')
fn1('44')

适用场景:

  • 搜索框输入联想(用户停止输入一段时间后再发送请求)
  • 窗口大小调整(resize)后重新计算布局
  • 表单验证(用户输入完成后再校验,而不是每输入一个字符就校验一次)

2.节流throttle

节流第一次是立即执行,后面的之前会根据上一次的时间戳,是否满足最大的延迟时间才再次执行。

固定时间只执行一次,不管你触发多少次(节流会稀释函数的执行频率)

//节流函数
function throttle(fn,delay) { 
    let last = 0;
    return (...args) => {
       let now = Date.now();//now的时间单位是 毫微秒 和 settimeout的delay是一致
       console.log("now",now,"last",last)
       if(now > last + delay ){
          last = now;
          fn.apply(this,args)//立刻执行原来定义的函数+ 参数
       }
    }
} 

function hello(info) {
   console.log("hello jason",info)
}

const testFn = throttle(hello,300) 
testFn("11")
testFn("22")
testFn("33")
setTimeout(() => { 
    testFn("44")
}, 2000);

适用场景:

  • 滚动加载更多内容(scroll)
  • 鼠标移动事件(mousemove),比如拖拽
  • 游戏中的按键频率限制
  • 高频点击提交按钮防止重复提交