JavaScript实现防抖与节流
1. 引言
有这么一种场景:某个页面表单按钮设置了点击提交事件,有时因为网络不好,点击后后台服务端很久才返回信息,然而用户因等待许久已经多次点击导致多次发送数据,实际上服务器只需要一次发送的数据即可
又比如说这么一种场景:某个页面设置监听的resize事件,一旦resize则重新渲染页面,有时用户会慢慢的拖动导致不断触发resize事件,频繁的触发重新渲染导致页面出现问题,实际上只需要在一段时间内执行最后一次resize事件的重新渲染即可
解决诸如上述场景的问题,可以使用防抖和节流
防抖(Debounce)和节流(Throttle)是两种常用的优化JavaScript性能的技术
2. 防抖
防抖是指在事件被触发后,等待一段时间后才执行回调函数。如果在这段时间内又触发了该事件,则重新计时。防抖常用于处理频繁触发的事件,如窗口大小调整、搜索框输入等。通过防抖可以减少事件回调的执行次数,从而提高性能和减少不必要的资源消耗
示例代码如下:
function debounce(func, delay) {
let timeoutId;
return function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(func, delay);
}
}
function handleResize() {
// 处理窗口大小调整的逻辑
}
window.addEventListener('resize', debounce(handleResize, 200));
防抖较为简单,就是等待一段时间后执行
3. 节流
节流是指在一段时间内只允许函数执行一次。如果在这段时间内多次触发该函数,只有某一次触发会执行,其余触发会被忽略。节流常用于处理高频率触发的事件,如滚动事件、鼠标移动事件等。通过节流可以控制函数的执行频率,从而提高性能和避免过多的计算或渲染
示例代码如下:
function throttle(func, delay) {
let lastExecTime = 0;
return function() {
const currentTime = Date.now();
if (currentTime - lastExecTime > delay) {
func();
lastExecTime = currentTime;
}
}
}
function handleScroll() {
// 处理滚动事件的逻辑
}
window.addEventListener('scroll', throttle(handleScroll, 200));
测试如下,未设置节流时,下图页面滑动触发11次scroll处理函数,设置节流后触发3次scroll处理函数:
未设置节流window.addEventListener('scroll', handleScroll):

设置节流window.addEventListener('scroll', throttle(handleScroll, 200)):

上述节流代码设置为只执行一段时间内的第一次,节流也可以设置为只执行最后一次,示例代码如下:
function throttle(func, delay) {
let timeoutId;
let lastExecTime = 0;
return function () {
const currentTime = Date.now();
if (currentTime - lastExecTime > delay) {
func();
lastExecTime = currentTime;
} else {
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
func();
lastExecTime = currentTime;
}, delay-(currentTime - lastExecTime));
}
}
}
function handleScroll() {
// 处理滚动事件的逻辑
console.log('scroll');
}
window.addEventListener('scroll', throttle(handleScroll, 200));
4. 区别
防抖是等待一段时间后执行,且只执行最后一次
节流是一段时间内只执行一次,执行第一次或最后一次都行
5. 第三方库
Lodash 是一个 JavaScript 实用工具库,包含了防抖和节流函数
修改防抖部分代码:
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script>
function handleResize() {
// 处理窗口大小调整的逻辑
console.log('resize');
}
window.addEventListener('resize', _.debounce(handleResize, 200));
</script>
修改节流部分代码:
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script>
function handleScroll() {
// 处理滚动事件的逻辑
console.log('scroll');
}
window.addEventListener('scroll', _.throttle(handleScroll, 200, { trailing: false }));
// trailing: false 表示禁用最后一次执行,即执行第一次
</script>
更为具体的函数API解释可查看文档:
6. 参考资料
[1] 前端性能优化篇: 防抖和节流 - 掘金 (juejin.cn)
[2] lodash.debounce | Lodash中文文档 | Lodash中文网 (lodashjs.com)
[3] lodash.throttle | Lodash中文文档 | Lodash中文网 (lodashjs.com)
JavaScript实现防抖与节流的更多相关文章
- javascript之防抖与节流
防抖 你是否在日常开发中遇到一个问题,在滚动事件中需要做个复杂计算或者实现一个按钮的防二次点击操作. 这些需求都可以通过函数防抖动来实现.尤其是第一个需求,如果在频繁的事件回调中做复杂计算,很有可能导 ...
- JavaScript:防抖与节流
①防抖: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...
- Javascript的防抖和节流、VUE的防抖和节流
js原生 函数防抖:将几次操作合并为一此操作进行.原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置.这样一来,只有最后一次操作能 ...
- javascript的防抖与节流
一.节流 一段时间内只能触发一次,如果这段时间内触发多次事件,只有第一次生效会触发回调函数,一段时间过后才能再次触发(一定时间内只执行第一次) 应用场景 1.鼠标连续不断地触发某事件(如点击),只在单 ...
- 原生JavaScript实现函数的防抖和节流
原生JavaScript实现函数的防抖和节流 参考:https://www.jianshu.com/p/c8b86b09daf0 想详细了解的直接戳上面链接了,讲得非常清楚.下面只给代码和我自己写的注 ...
- 来聊聊JavaScript中的防抖和节流
目录 JavaScript防抖和节流 问题还原 防抖 什么是防抖 使用场景 节流 什么是节流 使用场景 JavaScript防抖和节流 问题还原 我们先来通过代码把常见的问题还原: <html& ...
- 彻底搞懂JavaScript的闭包、防抖跟节流
最近出去面试了一下,收获颇多!!! 以前的我,追求实际,比较追求实用价值,然而最近面试,传说中的面试造火箭,工作拧螺丝,竟然被我遇到了.虽然很多知识点在实际工作中并不经常用到,但人家就是靠这个来筛选人 ...
- JavaScript 中的防抖和节流
什么是防抖 函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时.如下图,持续触发 scrol ...
- JavaScript中函数防抖、节流
码文不易,转载请带上本文链接,感谢~ https://www.cnblogs.com/echoyya/p/14565642.html 目录 码文不易,转载请带上本文链接,感谢~ https://www ...
- JavaScript中的防抖与节流-图文版
01.防抖还是节流 防抖 与 节流 目的都是避免一定时间内,大量重复的操作造成的性能损耗.因此原理也类似,都是阻止过多的事件执行,只保留一部分来执行.适用场景略有不同,也有交叉,动手练习一遍就懂了. ...
随机推荐
- Python内置小工具(非常实用!)
一.1秒钟启动一个下载服务器在工作中时不时会有这样的一个需求:将服务器(或者自己电脑)上的文件传给其他同事.将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输.但是,如果需要传 ...
- Linux 列出文件的绝对路径
1.使用ls中列出文件的绝对路径ls | sed "s:^:`pwd`/:" 2.列出当前目录下的所有文件(包括隐藏文件)的绝对路径, 对目录不做递归find $PWD -maxd ...
- 如何使用ASP.NET Core 中的 Hangfire 实现作业调度
https://procodeguide.com/programming/hangfire-in-aspnet-core-schedule-jobs/ 如何使用ASP.NET Core 中的 Hang ...
- Python 装饰器解析(一)
装饰器用于在源码中"标记"函数,以增强函数的行为. 我们先来看下面的例子,现有一个求和函数add,现在要求统计函数执行的时长 def add(a, b): print(a+b) 最 ...
- 【Unity3D】血条(HP)
1 需求实现 人机交互Input 中实现了通过键盘控制坦克运动,通过鼠标控制坦克发射炮弹,本文将在此基础上,增加血条(HP)功能.炮弹命中后,HP 值会减少,因此需要应用到 刚体组件Rigidbo ...
- 初探富文本之文档diff算法
初探富文本之文档diff算法 当我们实现在线文档的系统时,通常需要考虑到文档的版本控制与审核能力,并且这是这是整个文档管理流程中的重要环节,那么在这个环节中通常就需要文档的diff能力,这样我们就可以 ...
- leetcode 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 . 示例 1: 输入:root = [3,9,20,n ...
- 【Azure 应用服务】App Service 默认页面暴露Tomcat版本信息,存在安全风险
问题描述 在创建Azure App Service时,服务端的配置使用Java 8 + Tomcat 8.5.默认的根目录页面显示出App Service Tomcat版本信息,存在一定的安全隐患. ...
- Java 可变个数形参的方法
1 /** 2 * 3 * @Description 4 * @author Bytezero·zhenglei! Email:420498246@qq.com 5 * @version 6 * @d ...
- Failed to execute goal on project WebBackend: Could not resolve dependencies for project com.lang.yi:WebBackend:jar:1.0.0
一.问题由来 自己在搭建项目的时候报一个错误,如标题所示,具体错误信息如下: Failed to execute goal on project WebBackend: Could not resol ...