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实现防抖与节流的更多相关文章

  1. javascript之防抖与节流

    防抖 你是否在日常开发中遇到一个问题,在滚动事件中需要做个复杂计算或者实现一个按钮的防二次点击操作. 这些需求都可以通过函数防抖动来实现.尤其是第一个需求,如果在频繁的事件回调中做复杂计算,很有可能导 ...

  2. JavaScript:防抖与节流

    ①防抖: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <titl ...

  3. Javascript的防抖和节流、VUE的防抖和节流

    js原生 函数防抖:将几次操作合并为一此操作进行.原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置.这样一来,只有最后一次操作能 ...

  4. javascript的防抖与节流

    一.节流 一段时间内只能触发一次,如果这段时间内触发多次事件,只有第一次生效会触发回调函数,一段时间过后才能再次触发(一定时间内只执行第一次) 应用场景 1.鼠标连续不断地触发某事件(如点击),只在单 ...

  5. 原生JavaScript实现函数的防抖和节流

    原生JavaScript实现函数的防抖和节流 参考:https://www.jianshu.com/p/c8b86b09daf0 想详细了解的直接戳上面链接了,讲得非常清楚.下面只给代码和我自己写的注 ...

  6. 来聊聊JavaScript中的防抖和节流

    目录 JavaScript防抖和节流 问题还原 防抖 什么是防抖 使用场景 节流 什么是节流 使用场景 JavaScript防抖和节流 问题还原 我们先来通过代码把常见的问题还原: <html& ...

  7. 彻底搞懂JavaScript的闭包、防抖跟节流

    最近出去面试了一下,收获颇多!!! 以前的我,追求实际,比较追求实用价值,然而最近面试,传说中的面试造火箭,工作拧螺丝,竟然被我遇到了.虽然很多知识点在实际工作中并不经常用到,但人家就是靠这个来筛选人 ...

  8. JavaScript 中的防抖和节流

    什么是防抖 函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时.如下图,持续触发 scrol ...

  9. JavaScript中函数防抖、节流

    码文不易,转载请带上本文链接,感谢~ https://www.cnblogs.com/echoyya/p/14565642.html 目录 码文不易,转载请带上本文链接,感谢~ https://www ...

  10. JavaScript中的防抖与节流-图文版

    01.防抖还是节流 防抖 与 节流 目的都是避免一定时间内,大量重复的操作造成的性能损耗.因此原理也类似,都是阻止过多的事件执行,只保留一部分来执行.适用场景略有不同,也有交叉,动手练习一遍就懂了. ...

随机推荐

  1. STM32F401的外部中断EXTI

    stm32f401 EXTI EXTI就是External interrupt/event controller, 外部事件和中断控制器, 包含21条边沿检测线. 每条线可以独立设置触发事件(上升沿, ...

  2. 【Unity3D】程序纹理简单应用

    1 几何纹理应用 ​ 本文所有案例的完整资源详见→Unity3D程序纹理简单应用. 1.1 边框 ​ 1)边框子图 ​ Border.shadersubgraph ​ 说明:Any 节点用于判断输入向 ...

  3. 【Unity3D】UGUI之Button

    1 Button属性面板 ​ 在 Hierarchy 窗口右键,选择 UI 列表里的 Button 控件,即可创建 Button 控件,选中创建的 Button 控件,按键盘[T]键,可以调整 But ...

  4. Vue实现简单计算器功能

    知识点: v-model双向绑定 v-on事件绑定 实现效果 源码 <!DOCTYPE html> <html lang="en"> <head> ...

  5. vue+jsPlumb制成的流程图项目

    本项目参考:https://github.com/wangduanduan/visual-ivr 主页面如下:

  6. mybatis处理集合、数组参数使用in查询

    对于mybatis的参数类型是集合数组的时候进行查询. 第一种:参数list ,使用mybatis的标签 1 SELECT * FROM TABLE_NAME AS a WHERE 2 3 a.id ...

  7. Taro兼容h5的一些小问题

    背景:先做了小程序,现在需要兼容h5 问题一:Image组件mode属性设置为aspectFill在h5上没效果 解决方法:给img加样式 object-fit: cover (例子如下) // js ...

  8. OpenCV开发笔记(六十三):红胖子8分钟带你深入了解SIFT特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  9. ioutil.ReadDir读取目录下的内容

    func dirents(dir string) []os.FileInfo{ entries, err := ioutil.ReadDir(dir) // 读取目录并返回排好序的文件以及子目录名 i ...

  10. 【生成对抗网络学习 其二】GAN(keras实现)代码阅读笔记

    想来想去还是记录一下吧,主要是怕以后时间长忘了 好记性不如烂笔头 代码来自eriklindernoren的开源GAN实现:https://github.com/eriklindernoren/Kera ...