手把手教学----JavaScript防抖及节流实现

概念知识

        防抖事件(Event)触发时,对应的执行函数在执行等待时间内如果事件再次触发,则对应的执行函数重新开始执行,当执行等待时间结束,对应的执行函数开始执行。

  • 应用场景:input事件,当用户进行输入时,oninput事件一直会被触发,如果在input事件中有执行接口请求操作,则会导致频繁的请求接口,消耗过多性能处理输入事件,可添加函数防抖操作,在规定的时间内如果输入停止或中断,再请求相应的接口,这无疑会是释放系统资源

        节流当事件出现高并发工况时,事件对应的响应函数将会被频繁调用,大量占用系统资源,甚至可能导致系统宕机,为解决这一问题,限定单位时间内(运行周期),事件的响应函数只执行一次,到达下一周期时,如果事件再次触发,则函数可被再次调用一次。

  • 应用场景:在form表单提交时,如果遇到网络问题时,用户多次点击提交发现无反馈,如果一直点击提交,则在网络恢复后,会执行大量重复操作,加入节流操作后,则单位时间内(周期内),响应函数的执行只有一次,降低重复操作的频率,提升系统性能。

防抖及节流的实现与功能导出:

//debounce文件

// 防抖函数实现
// fn: 实现防抖的函数
// delay: 延迟的时间
// immediately: 是否立即执行(首次加载执行)
// resultCallback: 函数返回值回调函数

export function debounce(fn, delay, immediately = false, resultCallback = () => {}) {
  let timer = null;
  let args = arguments;
  let isInvoke = false;
  let result = null;
  let count = 0;
  try {
    // 入参合法判断
    if (typeof fn !== 'function') throw new Error(`ERR:: ${args[0]} not a funciton`);
    if (typeof delay !== 'number') throw new Error(`ERR:: ${args[1]} not a number`);
    if (typeof immediately !== 'boolean') throw new Error(`ERR:: ${args[2]} not a boolean`);
    if (typeof resultCallback !== 'function') throw new Error(`ERR:: ${args[3]} not a boolean`);

    return function (...arg) {
      // 第一次操作是否立即执行
      if (immediately && !isInvoke) {
        result = fn.apply(this, arg) + ` -> count >>> ${++count}`;
        resultCallback(result);
        isInvoke = true;
      }

      if (timer) {
        clearTimeout(timer);
      }

      timer = setTimeout(() => {
        result = fn.apply(this, arg) + ` -> count >>> ${++count}`;
        resultCallback(result);
        isInvoke = false;
      }, delay);

    }
  } catch (error) {
    console.log(error);
  }
}

// 节流函数实现
// fn: 实现防抖的函数
// delay: 延迟的时间
// immediately: 是否立即执行(首次加载执行)
// resultCallback: 函数返回值回调函数
export function throllte(fn, delay, immediately = false, resultCallback = () => {}) {
  let timer = null;
  let args = arguments;
  let isInvoke = false;
  let result = null;
  let count = 0;
  let status = true;
  try {
    // 入参合法判断
    if (typeof fn !== 'function') throw new Error(`ERR:: ${args[0]} not a funciton`);
    if (typeof delay !== 'number') throw new Error(`ERR:: ${args[1]} not a number`);
    if (typeof immediately !== 'boolean') throw new Error(`ERR:: ${args[2]} not a boolean`);
    if (typeof resultCallback !== 'function') throw new Error(`ERR:: ${args[3]} not a boolean`);

    return function (...arg) {
      // 第一次操作是否立即执行
      if (immediately && !isInvoke) {
        result = fn.apply(this, arg) + `count >>> ${++count}`;
        resultCallback(result);
        isInvoke = true;
      }
      if (status) {
        status = false;
        setTimeout(() => {
          result = fn.apply(this, arg) + `count >>> ${++count}`;
          status = true;
          resultCallback(result);
          isInvoke = false;
        }, delay);
      }
    }
  } catch (error) {
    console.log(error);
  }

}

ES-Module使用:

// main文件

import {
  debounce,
  throllte
}
from './debounce.js';

const item = document.querySelector("input");
const display = document.querySelector('p');
const switchMenu = document.querySelector("#switchMenu");
switchMenu.value = '';
switchMenu.onchange = () => {
  switch (+switchMenu.value) {
    case 1:
      item.oninput = debounce(lisen, 500, false, (result) => {
        display.innerText = result;
      });
      break;
    case 2:
      item.oninput = throllte(lisen, 2000, true, (result) => {
        display.innerText = result;
      })
      break;
    default:
      break;
  }
  console.log(switchMenu.value);
}

function lisen() {
  // console.log('输入监听事件');
  return 'this is a demo'
}

 Demo演示使用

演示HTML





  
  
  
  Document



  
这里显示操作结果:

使用效果

你可能感兴趣的:(javascript,前端,开发语言)