手写节流 throttle、防抖 debounce 原理、区别以及应用

122 阅读1分钟

节流:事件触发后,规定时间内,事件处理函数不能再次被调用。也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。

防抖:多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。也就是说,当一个事件被触发准备执行事件函数前,会等待一定的时间(这时间是码农自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行!

使用场景
节流:滚动加载更多、搜索框搜的索联想功能、高频点击、表单重复提交……
防抖:搜索框搜索输入,并在输入完以后自动搜索、手机号,邮箱验证输入检测、窗口大小 resize 变化后,再重新渲染

// 节流就是「技能冷却中」
const throttle = (fn, time) => {
  let 冷却中 = false
  return (...args) => {
    if(冷却中) return
    fn.call(undefined, ...args)
    冷却中 = true
    setTimeout(()=>{
      冷却中 = false
    }, time)
  }
}
// 还有一个版本是在冷却结束时调用 fn
// 简洁版,删掉冷却中变量,直接使用 timer 代替
const throttle = (f, time) => {
  let timer = null
  return (...args) => {
		if(timer) {return}
		f.call(undefined, ...args)
		timer = setTimeout(()=>{
		  timer = null
		}, time)
  }
}

使用方法:

防抖:

// 防抖就是「回城被打断」
const debounce = (fn, time) => {
  let 回城计时器 = null
  return (...args)=>{
    if(回城计时器 !== null) {
      clearTimeout(回城计时器) // 打断回城
    }
    // 重新回城
    回城计时器 = setTimeout(()=>{
      fn.call(undefined, ...args) // 回城后调用 fn
      回城计时器 = null
    }, time)
  }
}