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.防抖还是节流 防抖 与 节流 目的都是避免一定时间内,大量重复的操作造成的性能损耗.因此原理也类似,都是阻止过多的事件执行,只保留一部分来执行.适用场景略有不同,也有交叉,动手练习一遍就懂了. ...
随机推荐
- .NET Core开发实战(第14课:自定义配置数据源:低成本实现定制化配置方案)--学习笔记
14 | 自定义配置数据源:低成本实现定制化配置方案 这一节讲解如何定义自己的数据源,来扩展配置框架 扩展步骤 1.实现 IConfigurationSource 2.实现 IConfiguratio ...
- Miniconda 安装和使用笔记
Miniconda是Anaconda的简化版, 可以管理多个Python版本的环境. 实际使用的话, 占用的空间不会很小, 我跑一些正常的应用后, 安装目录占用空间4.3GB, 安装建议要预留10到2 ...
- CentOS在无网络环境下,用离线源yum安装软件
先说大致步骤: 1.前提假设:当前无网络的目标服务器是A,我们需要先准备一台服务器B: 2.在B上面用yum先把软件安装完成. 3.然后用createrepo将B中的包拷贝出来,并传到A上(用U盘或者 ...
- Vim常用快捷键汇总
跳到指定行 在命令行模式下输入: :n(n为指定行号)
- linux基本命令--day02
目录树架构示意图 以下是对这些目录的解释: /bin: bin是Binary的缩写, 这个目录存放着最经常使用的命令. /boot: 这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以 ...
- Redis高级系列详解
01-Redis系列之-Redis介绍安装配置 02-Redis系列之-架构和高级API的使用 03-Redis系列之-高级用法详解 04-Redis系列之-持久化(RDB,AOF) 05-Redis ...
- 【Azure Entra ID】如何在中国区获取用户 StrongAuthenticationUserDetails 和 StrongAuthenticationMethods 信息
问题描述 如何在中国区获取用户 StrongAuthenticationUserDetails 和 StrongAuthenticationMethods 信息 ? StrongAuthenticat ...
- 【应用服务 App Service】App Service For Linux 中如何挂载一个共享文件夹呢? Mount Azure Storage Account File Share
问题描述 使用Linux作为服务器运行Web App时,如何将 Storage Account 作为本地共享装载到 App Service for Linux / Container 中的应用呢? ...
- 【Azure 环境】使用Azure中的App Service部署Web应用,以Windows为主机系统是否可以启动防病毒,防恶意软件服务呢(Microsoft Antimalware)?
问题描述 使用Azure中的App Service部署Web应用,以Windows为主机系统是否可以启动防病毒,防恶意软件服务呢? Microsoft Antimalware for Azure is ...
- c++复习笔记——STL(vector)
c++-----STL容器系列(1) vector 1 介绍 Vector是stl容器中一种常见的容器 ,基本和数组类似,其大小(size)可变,常用于数组长度不确定时来代替数组,当数据超过vecto ...