手把手教学----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

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div>这里显示操作结果:<p></p>
  </div>
  <select name="switchMenu" id="switchMenu">
    <option value="1">防抖模式</option>
    <option value="2">节流模式</option>
  </select>
  <input type="text">
  <script type="module" src="./main.js"></script>
</body>

</html>

使用效果

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

David_leil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值