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)

image-20230725144058251

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

image-20230725144009779

上述节流代码设置为只执行一段时间内的第一次,节流也可以设置为只执行最后一次,示例代码如下:

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)

posted @   当时明月在曾照彩云归  阅读(200)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个适用于 .NET 的开源整洁架构项目模板
· API 风格选对了,文档写好了,项目就成功了一半!
· 【开源】C#上位机必备高效数据转换助手
· .NET 9.0 使用 Vulkan API 编写跨平台图形应用
· .NET 依赖注入中的 Captive Dependency
历史上的今天:
2022-07-26 基于C++的OpenGL 02 之着色器
点击右上角即可分享
微信分享提示