Skip to content
On this page

节流防抖

节流

设定一个时间点例如1秒,在一秒内的重复请求不会被执行
如果连续10秒都在发送这个请求,那么会出现每隔1秒执行一次这个请求
使用场景

  • 监听页面滚动
  • 监听DOM拖拽
  • 抢购疯狂点击

这里还加上了是否需要首次运行

js
function throttle(fn, time, isFirst = false) {
  let timeer = '';
  return function(...arg) {
    if (isFirst) {
      fn.call(this, ...arg); // 为了让函数内部的this正确指向
      isFirst = false;
    }
    if (timeer) return;
    timeer = setTimeout(() => {
      fn.call(this, ...arg);
      timeer = null
    }, time)
  }
}

测试

js
// 这里要用function,不能用箭头函数(箭头函数会导致this在初始化时就确定为window)
const fn = throttle(function(name, age) { 
  console.log(name, age, this);
}, 1000, true)

const obj = { age: 123 }

setInterval(() => {
  console.log(111);
  fn.call(obj, '', 100);
}, 200);

防抖

设定一个时间点例如1秒,在一秒内的再次请求都会让请求延迟一秒执行
如果连续10秒都在发送这个请求,那么会出现10秒后才会执行一次这个请求
使用场景

  • 输入框实时搜索

这里还加上了是否需要首次运行

js
function debounce(fn, time, isFirst = false) {
  let timeer = '';
  return function(...arg) {
    if (isFirst) {
      fn.call(this, ...arg);
      isFirst = false;
    }
    if (timeer) clearTimeout(timeer)
    timeer = setTimeout(() => {
      fn.call(this, ...arg);
    }, time)
  }
}

测试

js
const fn = debounce(function(name) {
  console.log(name, this);
}, 1000, true)

const obj = { age: 123 }
let inter = setInterval(() => {
  console.log(111);
  fn.call(obj, '');
}, 100);
setTimeout(() => {
  clearInterval(inter)
}, 2000);

额外的需求

time = 1000 的情况下
首次点击运行一次,一秒内的连续点击会清空上一次计时器,也就是首次点击后一秒内的连续点击是无效的
必须要再过一秒才能再次运行(与防抖不同的是: 防抖永远会执行一次,而此需求要的是一秒内的点击是无效的)

js
function selfDebounce(fn, time) {
  let timmer = '';
  return function (...arg) {
    if (timmer) {
      clearTimeout(timmer);
      timmer = setTimeout(() => {
        timmer = null;
      }, time);
      return;
    }
    timmer = setTimeout(() => {
      timmer = null;
    }, time);

    fn.call(this, ...arg);
  };
}