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.防抖还是节流 防抖 与 节流 目的都是避免一定时间内,大量重复的操作造成的性能损耗.因此原理也类似,都是阻止过多的事件执行,只保留一部分来执行.适用场景略有不同,也有交叉,动手练习一遍就懂了. ...
随机推荐
- NC16856 [NOI1999]钉子和小球.md
题目链接 题目 题目描述 有一个三角形木板,竖直立放,上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1).每颗钉子和周围的钉子的距离都等于d,每个格子的宽度也都等于d,且除了最左 ...
- golang常用库包:redis操作库go-redis使用(01)-Redis数据类型简介和连接Redis的几种方式
第一篇:go-redis使用,介绍Redis基本数据结构和其他特性,以及 go-redis 连接到Redis(本篇) https://www.cnblogs.com/jiujuan/p/1720716 ...
- 变量,六大数据类型之字符串、列表、元祖----day02
1.变量:可以改变的量,实际具体指的是内存中的一块存储空间 (1)变量的概念 (2)变量的声明 (3)变量的命名 (4)变量的交换 *常量就是不可改变的量,python当中没有明确定义常量的关键字,所 ...
- 【认知服务 Azure Cognitive Service】使用Azure Search中Create an Demo的示例时,出现空白页面的问题
问题描述 在根据Azure 认知服务的Search功能文档创建示例时(快速入门:在门户中创建演示应用(Azure 认知搜索)).完全相同的步骤,在中国区创建后下载Demo,查询结果一片空白:如下: 而 ...
- 【Azure App Service for Linux】Linux Web App如何安装系统未安装的包
问题描述 Linux Web App中如何安装系统默认未安装的包,如何来执行如 apt install XXX命令呢?现在遇见的问题时,通过Azure App Service门户中的SSH登录后,执行 ...
- 文心一言 VS 讯飞星火 VS chatgpt (205)-- 算法导论15.4 1题
一.求〈1,0,0,1,0,1,0,1〉和〈0,1,0,1,1,0,1,1,0〉的一个LCS.需要写代码的时候,请用go语言. 文心一言,代码正常运行: 在Go语言中,求两个序列的最长公共子序列(Lo ...
- 《Document-level Relation Extraction as Semantic Segmentation》论文阅读笔记
原文 代码 摘要 本文研究的是文档级关系抽取,即从文档中抽取出多个实体之间的关系.现有的方法主要是基于图或基于Transformer的模型,它们只考虑实体自身的信息,而忽略了关系三元组之间的全局信息. ...
- Android 安装手机程序有问题/点击runAPP 程序安装不了手机
可以在 gradle.properties 里添加 android.injected.testOnly=false 点击同步 就可以运行了 如下:
- Java 创建类,对象+调用方法
1 //测试类 2 public class PersonTest 3 { 4 public static void main(String[] args) 5 { 6 //创建Person类的对象 ...
- HW学习笔记
栈库分离方法注意事项: 所有用户输入数据需要进行分离过滤,不能遗漏.选择安全的过滤函数 如 mysql_real_escape_string(),避免过滤不严格导致注入 SQL查询模板需要设计安全,米 ...