函数防抖

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

函数防抖

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

🏕 生活中的实例:

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

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

  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
425 0
|
Linux
【Deepin 系统】Linux系统安装Halcon机器视觉工具
在Deepin Linux系统上安装Halcon机器视觉工具的详细步骤,包括下载安装包、安装、配置环境、复制license文件以及启动Halcon软件。
646 0
|
关系型数据库 分布式数据库 数据库
PolarDB闪电助攻,《香肠派对》百亿好友关系实现毫秒级查询
PolarDB分布式版助力《香肠派对》实现百亿好友关系20万QPS的毫秒级查询。
PolarDB闪电助攻,《香肠派对》百亿好友关系实现毫秒级查询
|
12月前
|
机器学习/深度学习 人工智能 自然语言处理
详谈什么是自然语言处理(NLP),特点以及使用场景场景(一)
详谈什么是自然语言处理(NLP),特点以及使用场景场景(一)
435 0
|
Linux 网络安全 开发工具
Linux 管理远程会话 screen:掌握终端的多任务操作
`Linux screen` 命令让多任务管理变得更简单,尤其在SSH连接远程服务器时。创建新会话如`screen -S backup`,查看会话`screen -ls`,退出`exit`。高级功能包括直接在会话中运行命令,如`screen vim memo.txt`,会话共享以协同工作,以及通过`screen -r`或`-D -r`重新连接或强制恢复断开的会话。提高效率,确保任务不间断运行。
274 1
|
存储 弹性计算 安全
阿里云活动内云服务器没有数据盘怎么办?购买后如何购买并挂载云盘?
在我们通过阿里云的活动来购买云服务器的时候,一般默认情况下只有系统盘,是没有数据盘的,但是很多用户处于实际使用需求和安全等方面的需求,通常都需要在购买之后单独再购买一块云盘作为数据盘挂载到云服务器上,本文以图文形式为大家展示阿里云活动内云服务器购买流程以及购买后如何购买并挂载云盘,适合新手用户参考。
阿里云活动内云服务器没有数据盘怎么办?购买后如何购买并挂载云盘?
|
安全 Nacos 开发者
Nacos报错问题之get请求路径带中文参数报错如何解决
Nacos是一个开源的、易于部署的动态服务发现、配置管理和服务管理平台,旨在帮助微服务架构下的应用进行快速配置更新和服务治理;在实际运用中,用户可能会遇到各种报错,本合集将常见的Nacos报错问题进行归纳和解答,以便使用者能够快速定位和解决这些问题。
|
机器人 Java
SpringBoot 实践项目(钉钉机器人)
我们在工作中钉钉办公需要一些提醒或者通知,需要用到钉钉机器人来代替我们完成一些重复性的工作,看到钉钉有个机器人的自定义文档。
712 1
SpringBoot 实践项目(钉钉机器人)
|
弹性计算 人工智能 算法
阿里云张伟:软件跨架构迁移(X86 -> ARM)的原理及实践|阿里云弹性计算技术公开课直播预告
针对阿里云倚天实例的软件迁移,阿里云为开发者提供了迁移工具EasyYitian和性能调优工具KeenTune,能够帮助用户解决软件迁移评估分析过程中人工分析投入大、准确率低、代码兼容性人工排查困难、迁移经验欠缺、反复依赖编译调错定位等痛点,实现业务在ARM ECS的快速适配。EasyYitian支持主流开发语言,通过系统自动化扫描可以一键生成分析报告。KeenTune通过AI算法与专家知识库的有效结合,为软件应用提供动态和静态协同调优的能力。
阿里云张伟:软件跨架构迁移(X86 -> ARM)的原理及实践|阿里云弹性计算技术公开课直播预告
|
开发框架 移动开发 前端开发
UniApp响应式布局
UniApp 是一款基于 Vue.js 开发的跨平台应用开发框架,可以同时构建 iOS、Android、H5 等多个平台的应用。在 UniApp 中,单位(Unit)是一个非常重要的概念,它决定了应用在不同设备上的布局和样式,要适应不同设备尺寸和屏幕方向的布局是一项艰巨的任务。UniApp 提供了多种方式来实现响应式布局。通过使用 Flex 布局、媒体查询、自适应单位和条件渲染,我们可以根据不同的屏幕尺寸和方向创建出适应性强的布局,从而提供更好的用户体验。
933 1