防抖函数~

防抖函数

防抖应用场景

  • 点击按钮发送消息, 避免用户快速点击发送多个请求.
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存

特性

  • 极其简单
  • this正确指向。实现作为事件回调函数,this的指向仍然是被绑定的事件的元素。event事件对象正确传递。
  • 增加立即执行功能。第一次触发(点击,输入等)会立即执行,后面在delay区间的触发会作为一次触发。
  • 可取消。返回cancel函数,执行即可取消此次触发的事件。场景:点击之后用户又立即点击了返回按钮,或点击返回首页,此次操作取消,不必再发送此次网络请求。
  • 返回执行函数的返回值

正文

基础防抖函数

使用input输入框演示

const ipt = document.querySelector('input');
ipt.addEventListener('input', debounce(onInput, 300))
function onInput(event) {
      console.log(123, this, event);
}
function debounce(fn, delay = 500) {
    
  let timer = null;
    
  const _debounce = function () {
      
    clearTimeout(timer); // 闭包
    timer = setTimeout(() => {
      fn();
    }, delay);
      
  }
    
  return _debounce;
}

this的指向正确与Event事件对象正确传递

function debounce(fn, delay = 500) {
    
  let timer = null;
  // 2.执行此debounce函数,返回一个函数,这个函数作为addEventListener传入的第二个参数,event对象自然也就传给了这个函数.用一个形参将其接收,再将其传给正真回调的函数.
  const _debounce = function (...agrs) {
      
    clearTimeout(timer); // 闭包
    timer = setTimeout(() => {
      // 这个函数作为 被监听元素 的回调函数, 该函数的this就会指向被监听元素元素.
      // 1.箭头函数不绑定this,自动去它的上层作用域找, 外层就是addEventListener传入的第二个参数,一个回调函数,它的this是正确的,指向的是触发事件的元素,绑定它即可.
      fn.apply(this, agrs);
    }, delay);
      
  }
    
  return _debounce;
}

首次事件触发立即执行

// 增加参数immediate默认false
function debounce(fn, delay = 500, immediate = false) {
  let timer = null;
    // 增加自己的控制参数. 
    // 依靠immediate也能做到. 尽量不要操作外界传入的东西.
  let isInvoke = false;

  const _debounce = function (...agrs) {
      // 判断
    if (immediate && !isInvoke) {
      fn.apply(this, agrs);
      // 已经调用一次
      isInvoke = true;;
    } else {
      clearTimeout(timer); // 闭包
      timer = setTimeout(() => {
        fn.apply(this, agrs);
        // delay时间到了执行完函数后改为false, 下次继续执行 第一次触发直接调用函数
        isInvoke = false;
      }, delay);
    }
  }
    
  return _debounce;
    
}

返回cancel函数

function debounce(fn, delay = 500, immediate = false) {
  let timer = null;
  let isInvoke = false;

  const _debounce = function (...agrs) {
    if (immediate && !isInvoke) {
      fn.apply(this, agrs);
      isInvoke = true;
    } else {
      clearTimeout(timer); // 闭包
      timer = setTimeout(() => {
        fn.apply(this, agrs);
        isInvoke = false;
      }, delay);
    }
  }
  // 函数既是函数又是对象, 给他再加一个cancel函数.
  _debounce.cancel = () => {
    if (timer) clearTimeout(timer);
  }

  return _debounce;
}

返回函数执行的返回值 & 最终形态

function debounce(fn, delay = 500, immediate = false, resultCallback = null) {
  let timer = null;
  let isInvoke = false;

  function _debounce(...agrs) {
    return new Promise((resolve, reject) => {
      if (immediate && !isInvoke) {
        const result = fn.apply(this, agrs);
        if (resultCallback) resultCallback(result);
        resolve(result)
        isInvoke = true;
      } else {
        clearTimeout(timer); // 闭包
        timer = setTimeout(() => {
          // 这个作为 元素input 的回调函数, 该函数的this就会指向input元素.
          // 箭头函数不绑定this,自动去它的上层作用域找, 外层就是addEventListener传入的第二个参数,一个函数,它的this是正确的,指向的是触发事件的元素.
          const result = fn.apply(this, agrs);
          if (resultCallback) resultCallback(result);
          resolve(result)
          isInvoke = false;
        }, delay);
      }
    })
  }

  _debounce.cancel = () => {
    if (timer) clearTimeout(timer);
    timer = null;
  }

  return _debounce;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值