实现防抖函数

145 阅读2分钟

一、防抖函数介绍

防抖:在一系列连续的事件触发后,只有最后一个事件才会触发处理函数

应用场景:用户在输入框中连续输入一串字符时,可以通过防抖策略,在输入完后,才执行查询的请求,可以有效减少请求次数,节约请求资源

二、功能实现

2.1基本功能

主要利用定时器实现,当多次触发事件,会检查上次timer是否存在(利用了闭包),存在则清除,然后重新设定定时器

function debounce(fn, delay) {
        let timer = null;

        const _debounce = function () {
          if (timer) clearTimeout(timer);

          timer = setTimeout(() => {
            fn();
            timer = null;
          }, delay);
        };

        return _debounce;
      }

运用

input.oninput =debounce(function(){
    console.log('111');
    },2000);

2.2优化参数和this指向问题

有时候fn函数需要使用event,或者使用this.value获取输入框的值,所以需要将参数传递给fn函数,并将fn的this进行绑定。

function debounce(fn, delay) {
        let timer = null;
        
        const _debounce = function (...args) {
          if (timer) clearTimeout(timer);

          timer = setTimeout(() => {
     //这里fn是独立函数调用,this指向了window,所以需要绑定this,指向为当前绑定事件的对象
            fn.apply(this, args);
            timer = null;
          }, delay);
        };

        return _debounce;
      }

运用

input.oninput =debounce(function(event){
    console.log('111',event,this.value);
    },2000);

2.3取消执行

函数也是对象,所以可以直接给返回的函数添加一个取消函数。

        //取消功能
        _debounce.cancel = function () {
          if (timer) clearTimeout(timer);
          
          timer = null;
        };

运用

    const debounceFn=debounce(function(event){
               console.log('111',event,this.value);
        },2000);
    
    input.oninput =debounceFn
    
     btn.onclick = function () {
          debounceFn.cancel();
      };

2.4立即执行

需要使用一个参数immediate决定是否立即执行,在使用isInvoke标记是否已经执行过了


function mydebounce(fn, delay, immediate = false) {
        let timer = null;
        let isInvoke = false; //是否执行过了
        let res = undefined;

        const _debounce = function (...args) {
          if (timer) clearTimeout(timer);
           //第一次执行
          if (!isInvoke && immediate) {
           fn.apply(this, args);
            isInvoke = true;
            return;
          }

          timer = setTimeout(() => {
            res = fn.apply(this, args);
            timer = null;
          }, delay);
        };

        //取消功能
        _debounce.cancel = function () {
          if (timer) clearTimeout(timer);
          timer = null;
          isInvoke = false;
        };

        return _debounce;
      }