防抖和节流-‘帕金森’网友的良方

前言

各位掘友们平时都没少上网噜,在冲浪的时候没少遇到过网络卡顿的情况,每当点击链接或者图片没有反应的时候,就会烦躁地一通乱点,那么掘友们有没有想过在你的一番操作之下,这个程序究竟在背地里运行了多少次?一次?好多次?好好好,今天我们就要来聊聊点点点的那些事。

防抖

掘友们从名字就能看出点门道来。防抖------就是防止 '帕金森' 网友的手抖。防抖是指在一定时间内,如果事件被频繁触发,只执行最后一次事件。可以用于优化一些高频率触发的事件,比如窗口大小改变,滚动事件等。也就是说当网友点击一个提交按钮后1s后进行提交,但是网友在1s内重复点击,那么就从最后一次点击开始计算1s后进行提交。

那么我们要如何实现这个效果呢?我们一起来看看:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<button id="btn">提交</button>
    <script> 
        function send(e){
            console.log(this,'提交完成',e);
        }
        let btn = document.getElementById('btn')
        btn.addEventListener('click',debounce(send,1000))
        function debounce(fn,delay){
            let timer;
            return function(){
                let args = arguments
                if(timer) clearTimeout(timer)
                timer= setTimeout(() => {
                    fn.call(this,...args)
                },delay)
            } 
        }
    </script>
</body>
</html>

首先我们设置了一个button用来模拟点击提交事件。接下来,为了监听按钮我们得在按钮上设置一个监听器。点击按钮以后,我们就运行debounce()

js 复制代码
 function debounce(fn,delay){
            let timer;
            return function(){
                let args = arguments
                if(timer) clearTimeout(timer)
                timer= setTimeout(() => {
                    fn.call(this,...args)
                },delay)
            } 
        }

debounce()中传入了两个参数,fndelayfn 是一个函数,也就是我们要进行的各种操作,也就是点击按钮后的一些操作,delay 就是我们设置的延迟时间。在函数体内,我们先声明了一个timer ,用来记录我们的计时器,如果在之前点击了按钮,那么timer 就不为空,当再次点击按钮时,判断timer 不为空,于是调用clearTimeout()方法,将定时器重置,实现在一定时间内只执行最后一次操作的效果。

细心的掘友会发现,如果我的send()方法中传入多个参数,那么怎么办呢?我们可以看到,在函数体内调用fn()方法的时候使用了解构,让fn()传入的实参解构再调用,那么无论fn()中有多少个形参,都能使用防抖。(不了解解构的掘友们请移步"跃迁ES6:探索JavaScript语言的最新进展(一)")

在这个防抖函数的实现中,fn 函数是通过 call() 方法调用的。具体来说,fn.call(this, ...args) 的作用是:将 fn 函数中的 this 指向当前上下文中的 this(也就是防抖函数返回的新函数的执行环境),并将传入的 args 参数展开后作为参数传递给 fn 函数。

节流

好好好,刚才我们从防抖的名字就能看出点门道来,那么这节流又是一个啥玩意?节流(throttle)指的是在一定时间间隔内只执行一次函数,用于优化高频率触发的事件,比如 scrollresizemousemove 等。与防抖不同的是,节流函数会按照固定的时间间隔执行函数,而不是在等待一段时间后才执行。

我们话不多说,先上代码:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id = "btn">提交</button>
</body>
<script>
    function send(){
        console.log('提交完成');
    }
    let btn = document.getElementById('btn')
    btn.addEventListener('click',throttle(send,1000))
    function throttle(fn,delay){
        let prevTime = Date.now()
        return function(){
           if(Date.now()-prevTime>delay){
             fn.apply(this,arguments)
             prevTime = Date.now()
           }
        }
    }
</script>
</html>

同样的我们看到throttle()方法

js 复制代码
function throttle(fn,delay){
        let prevTime = Date.now()
        return function(){
           if(Date.now()-prevTime>delay){
             fn.apply(this,arguments)
             prevTime = Date.now()
           }
        }
    }

与防抖方法不一样的地方是,不管我们在delay 这段时间内点击了多少次,我们只在 delay 时间过去后调用一次fn 方法。那么我们是如何记录时间的呢?这里使用到了Date.now(),这个方法返回的是现在距离1970年经过的毫秒数,储存在prevTime 变量中,如果后面的点击时间距离第一次点击时间大于delay 则运行 fn ,掘友们要注意的是,在运行以后,要将prevTime的时间进行更新,这样才能保证下一次点击事件的正确运行。

结尾

在实际开发中,合理地运用节流和防抖可以减少不必要的函数执行,降低资源消耗,提升页面响应速度。无论是处理 DOM 事件、AJAX 请求还是其他异步操作,都可以考虑使用节流和防抖来优化程序性能。希望本文对你有所帮助,也欢迎读者在实际项目中尝试运用这两种技巧,从而改善用户体验,提升应用性能。"

相关推荐
摘星编程32 分钟前
React Native + OpenHarmony:Stepper步进器组件
javascript·react native·react.js
野犬寒鸦33 分钟前
从零起步学习并发编程 || 第四章:synchronized底层源码级讲解及项目实战应用案例
java·服务器·开发语言·jvm·后端·学习·面试
●VON35 分钟前
React Native for OpenHarmony:简易计算器应用的开发与跨平台适配实践
javascript·react native·react.js
摘星编程8 小时前
OpenHarmony + RN:Placeholder文本占位
javascript·react native·react.js
a1117768 小时前
医院挂号预约系统(开源 Fastapi+vue2)
前端·vue.js·python·html5·fastapi
0思必得08 小时前
[Web自动化] Selenium处理iframe和frame
前端·爬虫·python·selenium·自动化·web自动化
行走的陀螺仪10 小时前
uni-app + Vue3编辑页/新增页面给列表页传参
前端·vue.js·uni-app
编程彩机10 小时前
互联网大厂Java面试:从Java SE到大数据场景的技术深度解析
java·大数据·spring boot·面试·spark·java se·互联网大厂
摘星编程11 小时前
React Native + OpenHarmony:Spinner旋转加载器
javascript·react native·react.js
We་ct11 小时前
LeetCode 205. 同构字符串:解题思路+代码优化全解析
前端·算法·leetcode·typescript