函数防抖

简介: 在频繁触发的情况下,只有足够的空闲时间,才执行代码一次,如果没有执行完就清除掉,重新执行逻辑。简单来说,当触发后再次触发,会取消上一次触发的执行,直到最后一次触发后过去设定时间后才执行。

函数防抖

函数防抖:在频繁触发的情况下,只有足够的空闲时间,才执行代码一次,如果没有执行完就清除掉,重新执行逻辑。简单来说,当触发后再次触发,会取消上一次触发的执行,直到最后一次触发后过去设定时间后才执行。

🏕 生活中的实例:

假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯;如果在电梯门块关闭之前,又有人来了,你会继续开门;这样一直进行下去,假定电梯没有容量限制,你可能需要等待几分钟,等到最终没人进电梯了,才会关闭电梯门,然后上楼。

函数防抖规定函数再次执行需要满足两个条件:

  1. 当调用事件触发一段时间后,才会执行该事件
  2. 在条件一等待的这段时间间隔内再次调用此动作则将重新计算时间间隔

实现原理

某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。

代码实现

当事件触发之后,必须等待设定的时间间隔之后,回调函数才会执行,假若在等待的时间内,事件又触发了则重新再等待设定的时间间隔,直到事件在设定的时间间隔内事件不被触发,那么最后一次触发事件后,则执行函数。

💡 实现思路:

将目标方法(动作)包装在定时器 setTimeout 里面,然后这个方法是一个事件的回调函数,如果这个回调函数一直执行,那么对应在运行的定时器通过设置 clearTimeout 进行清除,那么定时器内的目标方法也就不会执行,直到定时器的回调函数在时间间隔后开始执行,目标方法才被执行。

/**
 * 实现函数的防抖(目的是频繁触发中只执行一次)
 * @param func {function} 需要执行的函数
 * @param wait {number} 检测防抖的间隔频率,单位是毫秒(ms)
 * @return {function} 可被调用执行的函数
 */

function debounce(func, wait = 500, immediate = false) {
   
  let timer = null;

  // 返回一个函数,这个函数会在一个时间区间结束后的 wait 毫秒执行 func 函数
  return function (...args) {
   
    // 是否立即执行
    if (immediate) {
   
      fn.apply(this, args);
    }

    // 函数被调用,清除定时器
    timer && clearTimout(timer);

    // 当返回的函数被最后一个调用后(也就是用户停止了某个连续的操作)
    // 再过 wait 毫秒就执行 func
    // 这里直接使用箭头函数就不用保存执行上下文的引用了
    timer = setTimeout(() => {
   
      fn.apply(this, args);
    }, delay);
  };
}

其他框架库实现:Lodash Underscore

应用场景

函数防抖应用场景:连续事件的响应只需执行一次回调

  • 按钮提交场景:防止多次点击提交按钮,只执行最后提交的一次
  • 服务端验证场景:表单验证需要服务端配合,只执行一段连续的输入事件的最后一次,还有搜索联想词功能类似

总结:适合多次事件一次响应的情况

应用实践

注册实时验证

这里以用户注册时验证用户名是否被占用为例,如今很多网站为了提高用户体验,不会再输入框失去焦点的时候再去判断用户名是否被占用,而是在输入的时候就在判断这个用户名是否已被注册:

$('input.user-name').on('input', function () {
   
  $.ajax({
   
    url: `https://just.com/check`,
    method: 'post',
    data: {
   
      username: $(this).val(),
    },
    success(data) {
   
      if (data.isRegistered) {
   
        $('.tips').text('该用户名已被注册!');
      } else {
   
        $('.tips').text('恭喜!该用户名还未被注册!');
      }
    },
    error(error) {
   
      console.log(error);
    },
  });
});

很明显,这样的做法不好的是当用户输入第一个字符的时候,就开始请求判断了,不仅对服务器的压力增大了,对用户体验也未必比原来的好。而理想的做法应该是这样的,当用户输入第一个字符后的一段时间内如果还有字符输入的话,那就暂时不去请求判断用户名是否被占用。在这里引入函数防抖就能很好地解决这个问题:

$('input.user-name').on(
  'input',
  debounce(function () {
   
    $.ajax({
   
      url: `https://just.com/check`,
      method: 'post',
      data: {
   
        username: $(this).val(),
      },
      success(data) {
   
        if (data.isRegistered) {
   
          $('.tips').text('该用户名已被注册!');
        } else {
   
          $('.tips').text('恭喜!该用户名还未被注册!');
        }
      },
      error(error) {
   
        console.log(error);
      },
    });
  })
);

其实函数防抖的原理也非常地简单,通过闭包保存一个标记来保存 setTimeout 返回的值,每当用户输入的时候把前一个 setTimeout clear 掉,然后又创建一个新的 setTimeout,这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数了。

function debounce(fn, interval = 300) {
   
  let timeout = null;

  return function () {
   
    clearTimeout(timeout);

    timeout = setTimeout(() => {
   
      fn.apply(this, arguments);
    }, interval);
  };
}
目录
相关文章
|
芯片
最详细STM32,cubeMX 按键点亮 led
最详细STM32,cubeMX 按键点亮 led
773 0
|
8月前
|
机器学习/深度学习 人工智能 自然语言处理
AI Compass前沿速览:IndexTTS2–B站、HuMo、Stand-In视觉生成框架、Youtu-GraphRAG、MobileLLM-R1–Meta、PP-OCRv5
AI Compass前沿速览:IndexTTS2–B站、HuMo、Stand-In视觉生成框架、Youtu-GraphRAG、MobileLLM-R1–Meta、PP-OCRv5
730 10
AI Compass前沿速览:IndexTTS2–B站、HuMo、Stand-In视觉生成框架、Youtu-GraphRAG、MobileLLM-R1–Meta、PP-OCRv5
|
10月前
|
SQL 人工智能 关系型数据库
如何使用MySQL的事件调度器?
MySQL事件调度器允许在指定时间或间隔自动执行SQL语句,可用于数据清理、报告生成等任务。本文介绍其配置、创建、修改、删除事件的方法,并提供Java操作示例代码,帮助实现数据库定时任务管理。
439 0
|
关系型数据库 MySQL 数据库
mysql慢查询每日汇报与分析
通过启用慢查询日志、提取和分析慢查询日志,可以有效识别和优化数据库中的性能瓶颈。结合适当的自动化工具和优化措施,可以显著提高MySQL数据库的性能和稳定性。希望本文的详解和示例能够为数据库管理人员提供有价值的参考,帮助实现高效的数据库管理。
365 11
|
运维 Devops 应用服务中间件
自动化运维的利器:Ansible实战指南
【10月更文挑战第36天】在快速迭代的数字时代,自动化运维成为提升效率、减少错误的关键。Ansible以其简洁性、易用性和强大的功能脱颖而出。本文将带你了解Ansible的核心组件,通过实际案例深入其应用,并探讨如何结合最佳实践优化你的自动化工作流程。无论你是新手还是有经验的运维人员,本指南都将为你提供宝贵的知识和技能。
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
507 1
|
安全 Linux Shell
在Linux中,如何使用脚本进行系统配置和部署?
在Linux中,如何使用脚本进行系统配置和部署?
|
Kubernetes 网络协议 网络架构
使用containerlab搭建cilium BGP环境解析
使用containerlab搭建cilium BGP环境解析
529 4
|
Linux
【Deepin 系统】Linux系统安装Halcon机器视觉工具
在Deepin Linux系统上安装Halcon机器视觉工具的详细步骤,包括下载安装包、安装、配置环境、复制license文件以及启动Halcon软件。
1272 0
|
Linux iOS开发 MacOS
pyinstaller---Python代码的打包神器,一键将python代码打包成exe可执行文件
pyinstaller---Python代码的打包神器,一键将python代码打包成exe可执行文件
1721 0