【编程向导】JavaScript-函数类型之函数防抖-程序员宅基地

技术标签: 原型模式  javaScript知识图谱  # 函数类型  javascript  设计模式  开发语言  ecmascript  

函数防抖

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

生活中的实例:

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

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

  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);
  };
}

参考资料

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39357371/article/details/136551881

智能推荐

基于内核4.19版本的XFRM框架_linux的xfrm框架-程序员宅基地

文章浏览阅读794次,点赞2次,收藏5次。XFRM框架_linux的xfrm框架

织梦常用标签整理_织梦中什么页面用什么标签教学-程序员宅基地

文章浏览阅读774次。DedeCMS常用标签讲解笔记整理 今天我们主要将模板相关内容,在前面的几节课中已经基本介绍过模板标签的相关内容,大家可以下载天工开物老师的讲课记录:http://bbs.dedecms.com/132951.html,这次课程我们主要讲解模板具体的标签使用,并且结合一些实例来介绍这些标签。 先前课程介绍了,网站的模板就如同一件衣服,衣服的好坏直接决定了网站的好坏,很多网站一看界面_织梦中什么页面用什么标签教学

工作中如何编译开源工具(gdb)_gdb编译-程序员宅基地

文章浏览阅读2.5k次,点赞2次,收藏15次。编译是大部分工程师的烦恼,大家普遍喜欢去写业务代码。但我觉得基本的编译流程,我们还是需要掌握的,希望遇到相关问题,不要退缩,尝试去解决。天下文章一大抄,百度能解决我们90%的问题。_gdb编译

python简易爬虫v1.0-程序员宅基地

文章浏览阅读1.8k次,点赞4次,收藏6次。python简易爬虫v1.0作者:William Ma (the_CoderWM)进阶python的首秀,大部分童鞋肯定是做个简单的爬虫吧,众所周知,爬虫需要各种各样的第三方库,例如scrapy, bs4, requests, urllib3等等。此处,我们先从最简单的爬虫开始。首先,我们需要安装两个第三方库:requests和bs4。在cmd中输入以下代码:pip install requestspip install bs4等安装成功后,就可以进入pycharm来写爬虫了。爬

安装flask后vim出现:error detected while processing /home/zww/.vim/ftplugin/python/pyflakes.vim:line 28_freetorn.vim-程序员宅基地

文章浏览阅读2.6k次。解决方法:解决方法可以去github重新下载一个pyflakes.vim。执行如下命令git clone --recursive git://github.com/kevinw/pyflakes-vim.git然后进入git克降目录,./pyflakes-vim/ftplugin,通过如下命令将python目录下的所有文件复制到~/.vim/ftplugin目录下即可。cp -R ...._freetorn.vim

HIT CSAPP大作业:程序人生—Hello‘s P2P-程序员宅基地

文章浏览阅读210次,点赞7次,收藏3次。本文简述了hello.c源程序的预处理、编译、汇编、链接和运行的主要过程,以及hello程序的进程管理、存储管理与I/O管理,通过hello.c这一程序周期的描述,对程序的编译、加载、运行有了初步的了解。_hit csapp

随便推点

挑战安卓和iOS!刚刚,华为官宣鸿蒙手机版,P40搭载演示曝光!高管现场表态:我们准备好了...-程序员宅基地

文章浏览阅读472次。点击上方 "程序员小乐"关注,星标或置顶一起成长后台回复“大礼包”有惊喜礼包!关注订阅号「程序员小乐」,收看更多精彩内容每日英文Sometimes you play a..._挑战安卓和ios!华为官宣鸿蒙手机版,p40搭载演示曝光!高管表态:我们准备好了

精选了20个Python实战项目(附源码),拿走就用!-程序员宅基地

文章浏览阅读3.8w次,点赞107次,收藏993次。点击上方“Python爬虫与数据挖掘”,进行关注回复“书籍”即可获赠Python从入门到进阶共10本电子书今日鸡汤昔闻洞庭水,今上岳阳楼。大家好,我是小F。Python是目前最好的编程语言之一。由于其可读性和对初学者的友好性,已被广泛使用。那么要想学会并掌握Python,可以实战的练习项目是必不可少的。接下来,我将给大家介绍20个非常实用的Python项目,帮助大家更好的..._python项目

android在线图标生成工具,图标在线生成工具Android Asset Studio的使用-程序员宅基地

文章浏览阅读1.3k次。在网站的导航资源里看到了一个非常好用的东西:Android Asset Studio,可以在线生成各种图标。之前一直在用一个叫做Android Icon Creator的插件,可以直接在Android Studio的插件里搜索,这个工具的优点是可以生成适应各种分辨率的一套图标,有好几种风格的图标资源,遗憾的是虽然有很多套图标风格,毕竟是有限的。Android Asset Studio可以自己选择其..._在线 android 图标

android 无限轮播的广告位_轮播广告位-程序员宅基地

文章浏览阅读514次。无限轮播广告位没有录屏,将就将就着看,效果就是这样主要代码KsBanner.java/** * 广告位 * * Created by on 2016/12/20. */public class KsBanner extends FrameLayout implements ViewPager.OnPageChangeListener { private List

echart省会流向图(物流运输、地图)_java+echart地图+物流跟踪-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏6次。继续上次的echart博客,由于省会流向图是从echart画廊中直接取来的。所以直接上代码<!DOCTYPE html><html><head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /&_java+echart地图+物流跟踪

Ceph源码解析:读写流程_ceph 发送数据到其他副本的源码-程序员宅基地

文章浏览阅读1.4k次。一、OSD模块简介1.1 消息封装:在OSD上发送和接收信息。cluster_messenger -与其它OSDs和monitors沟通client_messenger -与客户端沟通1.2 消息调度:Dispatcher类,主要负责消息分类1.3 工作队列:1.3.1 OpWQ: 处理ops(从客户端)和sub ops(从其他的OSD)。运行在op_tp线程池。1...._ceph 发送数据到其他副本的源码