函数节流与函数防抖

news/2024/7/1 2:27:48

什么是函数节流与函数防抖

举个栗子,我们知道目前的一种说法是当 1 秒内连续播放 24 张以上的图片时,在人眼的视觉中就会形成一个连贯的动画,所以在电影的播放(以前是,现在不知道)中基本是以每秒 24 张的速度播放的,为什么不 100 张或更多是因为 24 张就可以满足人类视觉需求的时候,100 张就会显得很浪费资源。再举个栗子,假设电梯一次只能载一人的话,10 个人要上楼的话电梯就得走 10 次,是一种浪费资源的行为;而实际生活正显然不是这样的,当电梯里有人准备上楼的时候如果外面又有人按电梯的话,电梯会再次打开直到满载位置,从电梯的角度来说,这时一种节约资源的行为(相对于一次只能载一个人)。

  • 函数节流: 指定时间间隔内只会执行一次任务;
  • 函数防抖: 任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。

函数节流(throttle)

这里以判断页面是否滚动到底部为例,普通的做法就是监听 window 对象的 scroll 事件,然后再函数体中写入判断是否滚动到底部的逻辑:

function onScroll() {// 判断是否滚动到底部的逻辑const pageHeight = $('body').height();const scrollTop = $(window).scrollTop();const winHeight = $(window).height();const thresold = pageHeight - scrollTop - winHeight;if (thresold > -100 && thresold <= 20) {console.log('end');}
}$(window).on('scroll', onScroll);

throttle

这样做的一个缺点就是比较消耗性能,因为当在滚动的时候,浏览器会无时不刻地在计算判断是否滚动到底部的逻辑,而在实际的场景中是不需要这么做的,在实际场景中可能是这样的:在滚动过程中,每隔一段时间在去计算这个判断逻辑。而函数节流所做的工作就是每隔一段时间去执行一次原本需要无时不刻地在执行的函数,所以在滚动事件中引入函数的节流是一个非常好的实践:

$(window).on('scroll', throttle(onScroll));

throttle

加上函数节流之后,当页面再滚动的时候,每隔 300ms 才会去执行一次判断逻辑。

简单来说,函数的节流就是通过闭包保存一个标记(canRun = true),在函数的开头判断这个标记是否为 true,如果为 true 的话就继续执行函数,否则则 return 掉,判断完标记后立即把这个标记设为 false,然后把外部传入的函数的执行包在一个 setTimeout 中,最后在 setTimeout 执行完毕后再把标记设置为 true(这里很关键),表示可以执行下一次的循环了。当 setTimeout 还未执行的时候,canRun 这个标记始终为 false,在开头的判断中被 return 掉。

function throttle(fn, interval = 300) {let canRun = true;return function () {if (!canRun) return;canRun = false;setTimeout(() => {fn.apply(this, arguments);canRun = true;}, interval);};
}

函数防抖(debounce)

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

$('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);},});
});

debounce

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

$('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);},});
}));

throttle

其实函数防抖的原理也非常地简单,通过闭包保存一个标记来保存 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);};
}

总结

其实函数节流与函数防抖的原理非常简单,巧妙地使用 setTimeout 来存放待执行的函数,这样可以很方便的利用 clearTimeout 在合适的时机来清除待执行的函数。

使用函数节流与函数防抖的目的,在开头的栗子中应该也能看得出来,就是为了节约计算机资源。


http://lihuaxi.xjx100.cn/news/245070.html

相关文章

《Linux实践及应用》

2019独角兽企业重金招聘Python工程师标准>>> 《Linux实践及应用》 本书以RedHat 9.0为蓝本&#xff0c;系统地介绍Linux的基础知识、Linux系统的安装与配置、常用命令&#xff0c;以及如何进行Linux系统管理和基本的网络服务设置&#xff08;包括如何设置DNS服务器、…

c++中的对象引用(object reference)与对象指针的区别

2019独角兽企业重金招聘Python工程师标准>>> ★ 相同点&#xff1a; 1. 都是地址的概念&#xff1b; 指针指向一块内存&#xff0c;它的内容是所指内存的地址&#xff1b;引用是某块内存的别名。 ★ 区别&#xff1a; 1. 指针是一个实体&#xff0c;而引用仅是个…

蚂蚁金服天街:OceanBase 在大促 5 年来的技术演进

为了与金融从业者、科技从业者共同探讨金融 业务的深层次问题&#xff0c;蚂蚁金服联手 TGO 鲲鹏会&#xff0c;在 12 月 8 日举办了「走进蚂蚁金服&#xff1a;双十一背后的蚂蚁金服技术支持」活动。蚂蚁金服高级技术专家天街为大家分享了《蚂蚁双 11 大促 OceanBase 核心技术…

SpringCloud 面试题,最新SpringCloud 面试题,2020 SpringCloud 面试题

最近我一直在面试高级工程师&#xff0c;不管初级&#xff0c;高级&#xff0c;程序员&#xff0c;我想面试前&#xff0c;大家刷题一定是是少不了吧。 我也一样&#xff0c;我在网上找了很多面试题来看&#xff0c;最近又赶上跳槽的高峰期&#xff0c;好多粉丝&#xff0c;都…

percent之集合

2019独角兽企业重金招聘Python工程师标准>>> 这个留到明天再来写吧,今天把hub剩下的坑填掉. 转载于:https://my.oschina.net/u/2011113/blog/416458

Docker 入门到实践笔记2

Docker值得关注的特性&#xff1a;文件系统隔离&#xff1a;每个进程容器运行在一个完全独立的根文件系统里。资源隔离&#xff1a;系统资源像CPU和内存等可以分配到不同的容器中。网络隔离&#xff1a;每个进程容器运行在自己的网络空间&#xff0c;虚拟接口和IP地址。日志记录…

如何处理单元测试产生的数据,下列哪些说法是正确的

如何处理单元测试产生的数据&#xff0c;下列哪些说法是正确的&#xff1f;&#xff1a;答案在文末 A. 测试数据入库时加特殊前缀标识。B. 测试数据使用独立的测试库。C. 自动回滚单元测试产生的脏数据。D. 无须区别&#xff0c;统一在业务代码中进行判断和识别。 多选 关于用…

IDEA ctrl+alt+L 格式化快捷键无效时解决

这几天发现自己Intellij IDEA ctrlaltL格式化代码无效 设置里面按照快捷键搜索 按了 ctrlaltL 也没反应 但是我设置的确实是默认的 ctrlaltL 最后终于找到了问题所在 原来是开网易云音乐的锅 网易云会有一个全局的快捷键ctrlaltL跟idea冲突 去网易云关了就好了 转载于:https:/…