JavaScript的防抖和节流一起来了解下

目录
  • 1.前言
  • 2.函数防抖(debounce)
    • 延迟防抖
    • 前缘防抖
    • 防抖函数实现总结
  • 3.函数节流(throttling)
    • 延迟节流
    • 前缘节流
    • 节流函数实现总结
  • 4.两者区别
  • 5.应用场景
  • 总结

1. 前言

首先来举个例子。百度首页的百度输入框,用户输入的时候,每次输入的信息,我们都能看到百度服务器返回给我们的联想关键字。我们每改动一个字,它就换一次联想词,这是我们肉眼能看到的速度,实际上如果不加以处理,可能已经上服务器发起了好几十次的同一个关键字联想请求了,具体速度依赖于不同的pc等机器上的运行速度不同。那么,刚刚也谈到,对于同一个关键字,请求这么多次,也许想给用户呈现的就一次,剩下的请求都是浪费的,并且如果成千上万甚至上亿的用户同时请求,对服务器的负担是巨大的

防抖节流解决的问题:

在连续触发的事件中,事件处理函数的频繁调用会加重浏览器或服务器的性能负担导致用户体验糟糕,有哪些连续触发的事件呢 ?

比如,浏览器滚动条的滚动事件、浏览器窗口调节的resize事件、输入框内容校验以及在移动端的touchmove事件等。

所以,我们将采用防抖函数(debounce )和节流函数(throttle)来限制事件处理函数的调用频率

总的来说:防抖函数(debounce )和节流函数(throttle)是在时间轴上控制函数的执行次数

2. 函数防抖(debounce)

延迟防抖

延迟防抖(debounce): 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

生活中的实例: 如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次。

如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

如下图,持续触发click事件时,并不执行handle函数,当1000毫秒内没有触发click事件时,才会延时触发click事件。

前缘防抖

执行动作在前,然后设定周期,周期内有事件被触发,不执行动作,且周期重新设定。

为什么要这样呢?

试想第一种延迟debounce,我们本来想对用户输入的关键字,发起请求联想的频率降低,但是如果用户在我们设定的时间中,一直输入,导致的就是,用户一直看不到关键字,我们倒不如第一次输入的时候就发起一个请求,服务器返回结果,呈现给用户,然后后续用户的键入结束在继续请求)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>防抖</title>
</head>
<body>
    <button id="debounce1">点我防抖呐!</button>
<script>
    function handle() {
      console.log("防抖成功!");
    }
    window.onload = function() {
        // 1. 获取按钮,并绑定事件
        var myDebounce = document.getElementById('debounce1');
        myDebounce.addEventListener('click',debounce(handle,1000,true));
    }
    // 防抖函数
    function debounce(fn,wait, immediate ){
        //2. 设置时间戳,使用setTimeout让返回函数延迟执行
        let timer, result;
        return function(...args){
            // 3. timer存在,将定时器中的函数清除
            if(timer) clearTimeout(timer);
            // 4.1 立即执行返回函数
            if(immediate){
                if(!timer){
                    result = fn.apply(this,args);
                }
                timer = setTimeout(() => {
                    timer = null;
                },wait);
            }else{  // 4.2 非立即执行返回函数
                timer = setTimeout(() => {
                    fn.apply(this,args);
                },wait);
            }
        }
        // 5. 立即执行时返回函数的返回值
        return result;
    }
</script>
</body>
</html>

实现效果:

原理解析:

  • 防抖函数作用,对传入的函数进行延时包装后返回
  • setTimeout在前一次未执行完前,第二次次触发将会覆盖掉前面的定时器,执行第二次的功能
  • 前一次由于异步加延时还未执行完,使用clearTimeout清除前面定时器,取消上次的fn功能
  • 为保持fn内部this的指向,使用apply改变this指向
  • fn传入为函数,不是函数的调用

防抖函数实现总结

function debounce(fn,wait, immediate ){
    //2. 设置时间戳,使用setTimeout让返回函数延迟执行
    let timer, result;
    return function(...args){
        // 3. timer存在,将定时器中的函数清除
        if(timer) clearTimeout(timer);
        // 4.1 立即执行返回函数
        if(immediate){
            if(!timer){
                result = fn.apply(this,args);
            }
            timer = setTimeout(() => {
                timer = null;
            },wait);
        }else{  // 4.2 非立即执行返回函数
            timer = setTimeout(() => {
                fn.apply(this,args);
            },wait);
        }
    }
    // 5. 立即执行时返回函数的返回值
    return result;
}

3. 函数节流(throttling)

throttling,节流的策略是,固定周期内,只执行一次动作,若有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期。 节流策略也分前缘和延迟两种。

与debounce类似,延迟是指 周期结束后执行动作,前缘是指执行动作后再开始周期。

  • 节流会稀释函数的执行频率
  • 在持续触发事件的过程中,函数会立即执行,并且每n秒执行一次

生活中的实例: 我们知道目前的一种说法是当 1 秒内连续播放 24 张以上的图片时,在人眼的视觉中就会形成一个连贯的动画,所以在电影的播放(以前是,现在不知道)中基本是以每秒 24 张的速度播放的,为什么不 100 张或更多是因为 24 张就可以满足人类视觉需求的时候,100 张就会显得很浪费资源

延迟节流

前缘节流

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节流</title>
</head>
<body>
    <button id="debounce1">点我节流呐!</button>
<script>
    function handle() {
      console.log("节流成功!");
    }
    window.onload = function() {
        var myDebounce = document.getElementById('debounce1');
        myDebounce.addEventListener('click',throttling(handle,1000,false));
    }
    // 节流函数
    function throttling(fn,wait,immediate){
        let timer;
        return function(...args) {
            if(!timer){
                if(immediate){
                    fn.apply(this,args);
                }
                timer = setTimeout(() => {
                    if(!immediate) {
                        fn.apply(this,args);
                    }
                    timer = null;
                },wait);
            }
        }
    }
</script>
</body>
</html>

实现效果:

节流函数实现总结

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节流</title>
</head>
<body>
    <button id="debounce1">点我节流呐!</button>
<script>
    function handle() {
      console.log("节流成功!");
    }
    window.onload = function() {
        var myDebounce = document.getElementById('debounce1');
        myDebounce.addEventListener('click',throttling(handle,1000,false));
    }
    // 节流函数
    function throttling(fn,wait,immediate){
        let timer;
        return function(...args) {
            if(!timer){
                if(immediate){
                    fn.apply(this,args);
                }
                timer = setTimeout(() => {
                    if(!immediate) {
                        fn.apply(this,args);
                    }
                    timer = null;
                },wait);
            }
        }
    }
</script>
</body>
</html>

4. 两者区别

函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

函数防抖只是在最后一次事件后才触发一次函数。

比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

5. 应用场景

对于函数防抖,有以下几种应用场景:

  • 给按钮加函数防抖防止表单多次提交。
  • 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
  • 判断scroll是否滑到底部,滚动事件+函数防抖

总的来说,适合多次事件一次响应的情况

对于函数节流,有如下几个场景:

  • 游戏中的刷新率
  • DOM元素拖拽
  • Canvas画笔功能

总的来说,适合大量事件按时间做平均分配触发。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • JavaScript中函数的防抖与节流详解

    目录 一.函数的节流 1.1定义 1.2解决方法 1.3案例演示 1.3.1 代码演示 1.3.2 运行结果 1.3.3 添加函数节流操作 1.3.4 运行结果 二.函数的防抖 2.1 定义 2.2 解决方法 2.3 案例演示 2.3.1 代码展示 2.3.2 运行结果 2.3.3添加函数防抖操作 2.3.4 运行结果 总结 一.函数的节流 1.1 定义 同时触发多次函数执行,执行的是相同内容,要求只执行第一次请求. 例如scroll事件,鼠标滚动一次触发多次函数执行,只需要执行一次. 1.2

  • javascript的防抖和节流你了解吗

    一:为什么需要防抖与节流 防抖和节流都是为了解决短时间内大量触发某函数或者事件而导致的性能问题,比如在 1.用户体验上,触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死,卡顿的现象 2.服务器上:加重服务器压力 二:防抖 防抖是当事件或函数被触发后,延迟n秒后在执行回调,如果在这n秒内事件或函数又被触发,则重新计时,直到n秒内没有触发事件或函数,则执行回调函数 图文解释: (回城的时间就相当于延迟时间,如果在回城的时间内再次触发回城则重新倒计时回城时间) 案例:表单输入框事件 <!DOC

  • 关于JavaScript防抖与节流的区别与实现

    目录 1.防抖 2.节流 3.总结 前言: 作为前端开发中会以下两种需求 (1)搜索需求 搜索的逻辑就是监听用户输入事件,等用户输入完成之后把数据发送给后端,后端返回匹配数据,前端显示数据到页面.如果只要用户输入就发请求,这样会给后端造成请求压力,需要控制请求的频率. (2)页面无限加载数据 页面无限加载数据的逻辑就是监听用户用户滚动事件,在用户滚动的过程中,去请求下一页的数据来显示到页面.,那么只要滚动就去发请求,同样会造成后端请求压力,需要控制请求的频率. 以上两种看起来都是控制请求频率的问

  • javascript的防抖节流函数解析

    目录 防抖节流函数的解析 认识防抖和节流函数 认识防抖debounce函数 防抖函数的案例 认识节流throttle函数 节流函数的应用场景 自定义防抖和节流函数 总结 防抖节流函数的解析 认识防抖和节流函数 防抖和节流的概念其实最早并不是出现在软件工程中,防抖是出现在电子元件中,节流出现在流体流动中 而JavaScript是事件驱动的,大量的操作会触发事件,加入到事件队列中处理. 而对于某些频繁的事件处理会造成性能的损耗,我们就可以通过防抖和节流来限制事件频繁的发生: 防抖和节流函数目前已经是

  • 浅谈JavaScript节流与防抖

    目录 节流与防抖 概念: 区别 节流实现 节流函数 防抖实现 防抖函数 防抖升级版 总结 节流与防抖 概念: 区别 节流实现 节流函数 防抖实现 防抖函数 防抖升级版 总结 节流与防抖 背景:当我们频繁去请求资源.接口等其他的时候,就会造成操作Dom频繁,接口压力大等等,性能下降.比如我有时候会每次搜索会猛地敲回车,在网络不很好的时候,点击下一页按钮的时候也会一直点,可能网络不好也可能服务器性能低. 为了避免频繁触发同一事件或请求,这时候就要用到节流和防抖了. what?这是啥?当我第一次听到这

  • JavaScript的防抖和节流一起来了解下

    目录 1.前言 2.函数防抖(debounce) 延迟防抖 前缘防抖 防抖函数实现总结 3.函数节流(throttling) 延迟节流 前缘节流 节流函数实现总结 4.两者区别 5.应用场景 总结 1. 前言 首先来举个例子.百度首页的百度输入框,用户输入的时候,每次输入的信息,我们都能看到百度服务器返回给我们的联想关键字.我们每改动一个字,它就换一次联想词,这是我们肉眼能看到的速度,实际上如果不加以处理,可能已经上服务器发起了好几十次的同一个关键字联想请求了,具体速度依赖于不同的pc等机器上的

  • 浅析JavaScript 函数防抖和节流

    函数防抖和节流都是对高频动作触发回调函数的一个优化,实现方式上有类似之处.先从使用场景做个区分. 防抖使用场景: 表单输入框校验 提交按钮避免重复提交 节流使用场景: scroll,mousemove,resize等 函数防抖(debounce) 表单输入框校验在用户不停的打字输入时并不需要向后台校验文本,只有当用户停下来一定时间后,这时候默认用户已经输入完毕了可以开始向后台提交文本了. 表单的提交按钮被用户多次连续点击时,显然并不需要每次点击都提交表单.仅在用户不点击之后,把最后一次的点击操作

  • JavaScript的防抖和节流案例

    目录 防抖 节流: 防抖:在一定的时间内只执行最后一次任务: 节流:一定的时间内只执行一次: 防抖 <button id="debounce">点我防抖!</button> $('#debounce').on('click', debounce()); function debounce() { let timer; // 闭包 return function () { clearTimeout(timer); timer = setTimeout(() =&g

  • 什么是JavaScript的防抖与节流

    目录 一.函数防抖(debounce) 1. 什么是防抖? 二.函数节流 2.1 定时器实现 2.2 时间戳实现 2.3 时间戳+定时器 一.函数防抖(debounce) 1. 什么是防抖? 函数防抖: 在频繁触发某一个事件时,一段时间内不再触发该事件后才会去调用对应的回调函数,在设定间隔时间内如果下一次事件被触发, 那么就重新开始定时器,直到事件触发结束. 规定时间内没有继续触发事件的前提下,再去调用事件处理函数: 具体如下面的例子所示: /*定义防抖函数 * func:传入一个函数,事件不再

  • JavaScript中防抖和节流的区别及适用场景

    目录 前言 防抖 例如 代码演示 节流 例如 代码演示 前言 防抖和节流,这个在我们的前端生涯中,这两个名词肯定不陌生,甚至经常被人问起: 两者有什么区别? 分别用于什么场景? ps:这就是高频的面试题了吧! 防抖 防抖是什么呢? 形象的的说就是:防止抖动(防抖函数内心独白:“你就抖动吧!等你不抖动了,我们在进行下一步”) 例如 一个搜索输入框, 用户不停的进行输入(这个时候就是抖动的过程), 等用户输入停止之后,再触发搜索. 代码演示 function debounce(fn, delay =

  • JavaScript中防抖和节流的实战应用记录

    目录 前言 为什么我们需要防抖/节流 防抖 节流 总结 前言 你可能会遇到这种的情况,一个站点使用自动填充的文本框,内容的拖拽,效果的滚动.那么,你遇到防抖和截流的概率还是很高的.为了使得这些操作,比如自动填充能够顺畅工作,你需要引入防抖和截流功能. 防抖 -> Debounce 节流 -> Throttle 为什么我们需要防抖/节流 开篇已经简单提了,debounce/throttle 能让你的站点表现更优异.它们工作原理是通过减少动作发起的次数.我们简单举个例子,自动填充文本框触发接口请求

  • 老生常谈Javascript的防抖和节流

    目录 1. 什么是防抖 2.什么是节流 3.节流阀 总结 1. 什么是防抖 [解释]: 防抖策略(debounce)是当事件被触发后,延迟 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时. [图解]: [作用]: 当用户频繁触发该事件的时候,确保只进行最后一次的请求操作,节约请求的资源 [实现输入框的防抖]: var timer = null // 1. 防抖动的 timer function debounceSearch(keywords) { // 2. 定义防抖的函数 ti

  • JavaScript 防抖和节流遇见的奇怪问题及解决

    场景 网络上已经存在了大量的有关 防抖 和 节流 的文章,为何吾辈还要再写一篇呢?事实上,防抖和节流,吾辈在使用中发现了一些奇怪的问题,并经过了数次的修改,这里主要分享一下吾辈遇到的问题以及是如何解决的. 为什么要用防抖和节流? 因为某些函数触发/调用的频率过快,吾辈需要手动去限制其执行的频率.例如常见的监听滚动条的事件,如果没有防抖处理的话,并且,每次函数执行花费的时间超过了触发的间隔时间的话 – 页面就会卡顿. 演进 初始实现 我们先实现一个简单的去抖函数 function debounce

随机推荐