带你理清防抖函数debounce的实现原理

234 阅读1分钟

面试题:请实现一个 debounce 函数,跑通测试用例

async function run() {
  const a1 = debounce(console.log, 50)

  a1(1, 2)
  await sleep(10)
  a1(2, 3)
  await sleep(20)
  a1(3, 4)
  await sleep(30)
  a1(4, 5)
  await sleep(40)
  a1(5, 6)
  // 经过 50 毫秒(近似),只打印出 5 6

  await sleep(51)
  a1(6, 7)
  // 打印出 6 7
}

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

run()

什么?什么是快乐星球?? hetui

什么是防抖函数?我想想,记不得了。

平时下拉框模糊搜索好像用到,大概是 连续输入的时候不触发函数执行,等停止输入 xx 秒后才执行

观察测试用例中 debounce 接受2个参数,并返回一个函数,可以写出如下结构

// 首先 debounce 返回一个函数
function debounce(fn, wait) {
  return () => {}
}

联想到当连续输入时,输入停止 wait 秒后执行函数,需要定时器,可以写出如下结构

function debounce(fn, wait) {
  return (...rest) => {
    setTimeout(() => {
      fn(rest)
    }, wait)
  }
}

当多次输入时,要清空之前的定时器,只留最后一个执行,执行完要销毁,可以写出如下结构

function debounce(fn, wait) {
  let timer = null
  return (...rest) => {
    // 如果timer存在,代表在未达到wait时,又输入了,需要重新计时
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      if (fn) {
        fn(rest)
        timer = null
      }
    }, wait)
  }
}

你学会了吗?