JavaScript防抖动与节流处理

针对一些会频繁触发的事件如scroll、resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能。

因此针对这类事件要进行防抖动或者节流处理

防抖动

它的做法是限制下次函数调用之前必须等待的时间间隔。正确实现 debouncing 的方法是将若干个函数调用合成 一次,并在给定时间过去之后仅被调用一次。

// 将会包装事件的 debounce 函数
function debounce(fn, delay) {
  // 维护一个 timer
  let timer = null;

  return function() {
    // 通过 ‘this' 和 ‘arguments' 获取函数的作用域和变量
    let context = this;
    let args = arguments;

    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  }
}
// 当用户滚动时被调用的函数
function foo() {
  console.log('You are scrolling!');

}

// 在 debounce 中包装我们的函数,过 2 秒触发一次
let elem = document.getElementById('container');
elem.addEventListener('scroll', debounce(foo, 2000));

首先,我们为scroll事件绑定处理函数,这时debounce函数会立即调用,因此给scroll事件绑定的函数实际上是debounce内部返回的函数

每一次事件被触发,都会清除当前的 timer 然后重新设置超时调用。
这就会导致每一次高频事件都会取消前一次的超时调用,导致事件处理程序不能被触发

只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行
更进一步,我们不希望非要等到事件停止触发后才执行,我希望立刻执行函数,然后等到停止触发 n 秒后,才可以重新触发执行。
这里增加一个immediate参数来设置是否要立即执行:

function debouce(func,delay,immediate){
    var timer = null;
    return function(){
        var context = this;
        var args = arguments;
        if(timer) clearTimeout(time);
        if(immediate){
            //根据距离上次触发操作的时间是否到达delay来决定是否要现在执行函数
            var doNow = !timer;
            //每一次都重新设置timer,就是要保证每一次执行的至少delay秒后才可以执行
            timer = setTimeout(function(){
                timer = null;
            },delay);
            //立即执行
            if(doNow){
                func.apply(context,args);
            }
        }else{
            timer = setTimeout(function(){
                func.apply(context,args);
            },delay);
        }
    }
}

节流

节流是另一种处理类似问题的解决方法。
节流函数允许一个函数在规定的时间内只执行一次。

它和防抖动最大的区别就是,节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

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

主要有两种实现方法:

var throttle = function(func,delay){
    var prev = Date.now();
    return function(){
        var context = this;
        var args = arguments;
        var now = Date.now();
        if(now-prev>=delay){
            func.apply(context,args);
            prev = Date.now();
        }
    }
}

当高频事件触发时,第一次应该会立即执行(给事件绑定函数与真正触发事件的间隔如果大于delay的话),而后再怎么频繁触发事件,也都是会每delay秒才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了。

定时器实现:

当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行;直到delay秒后,定时器执行执行函数,清空定时器,这样就可以设置下个定时器。

var throttle = fucntion(func,delay){
    var timer = null;

    return funtion(){
        var context = this;
        var args = arguments;
        if(!timer){
            timer = setTimeout(function(){
                func.apply(context,args);
                timer = null;
            },delay);
        }
    }
}

当第一次触发事件时,肯定不会立即执行函数,而是在delay秒后才执行。
之后连续不断触发事件,也会每delay秒执行一次。
当最后一次停止触发后,由于定时器的delay延迟,可能还会执行一次函数。

可以综合使用时间戳与定时器,完成一个事件触发时立即执行,触发完毕还能执行一次的节流函数:

var throttle = function(func,delay){
    var timer = null;
    var startTime = Date.now();

    return function(){
        var curTime = Date.now();
        var remaining = delay-(curTime-startTime);
        var context = this;
        var args = arguments;

        clearTimeout(timer);
        if(remaining<=0){
            func.apply(context,args);
            startTime = Date.now();
        }else{
            timer = setTimeout(func,remaining);
        }
    }
}

需要在每个delay时间中一定会执行一次函数,因此在节流函数内部使用开始时间、当前时间与delay来计算remaining,当remaining<=0时表示该执行函数了,如果还没到时间的话就设定在remaining时间后再触发。当然在remaining这段时间中如果又一次发生事件,那么会取消当前的计时器,并重新计算一个remaining来判断当前状态。

总结

防止一个事件频繁触发回调函数的方式:

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

节流:使得一定时间内只触发一次函数。
它和防抖动最大的区别就是,节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而防抖动只是在最后一次事件后才触发一次函数。
原理是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器。

到此这篇关于JavaScript防抖动与节流处理的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • JavaScript函数防抖动debounce

    目录 防抖动简述 防抖应用示例 1.防抖前后示例效果截图 2.防抖示例完整 demo 防抖动的应用场景 防抖动简述 函数防抖动(debounce):防止在短时间内过于频繁的执行相同的任务. 当短时间内的频繁是不必要的时候,就可以考虑去抖动,避免资源浪费,或造成不好体验. 函数防抖动的原理,主要是利用一次性定时器,延迟任务的执行,在延迟这段时间内, 如果任务再次被触发,则通过 clearTimeout 销毁上一次产生的定时器, 因为定时器的被销毁,之前被延迟执行的任务也会随之被取消执行. 这样就实

  • JavaScript防抖与节流详解

    目录 防抖debounce 节流throttle 总结 防抖debounce 定义:对于短时间内连续触发的事件,比如滚动事件,防抖就是让某个时间期限内,事件处理函数只执行一次. 关于防抖,拿手指按压弹簧举例,用手指按压弹簧,一直按住,弹簧将不会弹起直到松开手指. 举例resize: function debounce(fn, wait){ var timer = null; return ()=>{ if(timer !== null){ clearTimeout(timer); } timer

  • 通过实例讲解JS如何防抖动

    前言 这道题目经常与事件触发器同时存在,为了考察面试者在一些具体业务流程上(信息流,搜索框输入查询)等,能否综合的考虑实现思路. 题目 在某些信息列表中一般采用瀑布流,滚动一屏时加载相应的数据,请思考如何避免连续下拉时而产生的问题(可能是页面崩溃,也可能是巨卡无比). 一般情况下,如果碰到这样的面试题,防抖动机制,就能很好的解决,这方面最早的应用实践还是Twitter,开发者写了一篇博客,详细的阐述了如何解决这样的问题.那么,说到防抖动,其核心内涵在于延迟处理,也就是将一系列的事件处理程序全部延

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

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

  • JavaScript防抖与节流的实现与注意事项

    目录 概念 实现 测试 注意事项 总结 概念 防抖:点击N次提交按钮,只有最后一次会发出请求.减少无效请求的次数. 节流:每点击一次按钮,都会失效一段时间.降低触发的频率. 实现 /* 防抖 时限内,只有最后一次调用会执行 */ function debounce(func, interval = 0) { let timer; return function () { if (timer) { clearTimeout(timer); } timer = setTimeout(() => {

  • 浅谈JavaScript节流与防抖

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

  • JavaScript运动框架 解决防抖动问题、悬浮对联(二)

    本文实例是对JavaScript运动框架(一)的应用 scrollTop:有时候网页很长,其高度大于显示器高度,会产生滚动,那么在高度方向上,"滚走"的部分就是scrollTop var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; offsetTop:此属性可以获取元素的上外缘距离最近采用定位父元素内壁的距离,如果父元素中没有采用定位的,则是获取上外边缘距离文档内壁的距离.所谓的定

  • 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深入理解节流与防抖

    目录 一.js防抖和节流 二.为什么滚动scroll.窗口resize等事件需要优化 三.滚动和页面渲染前端性能优化的关系 四.防抖Debounce 1 防抖Debounce情景 2 防抖原理 3 防抖函数简单实现 4 防抖函数的演化过程 ①this event绑定问题 ②立即触发问题 ③返回值问题 ④取消防抖,添加cancel方法 五.节流Throttle 1 节流Throttle情景 2 节流原理 3 节流实现—时间戳和定时器 4 节流函数的演化过程 ①时间戳触发 ②定时器触发 ③结合时间戳

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

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

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

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

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

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

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

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

  • JavaScript 防抖和节流详解

    目录 防抖 节流 总结 防抖 自动门感应到有人,打开门,并且开始5秒倒计时,在 5 s 内有另外一个人靠近到门,门感应到人,重新5秒倒计时 当事件被触发时,设定一个延迟,若期间事件又被触发,则重新设定延迟,直到延迟结束,执行动作 (防止多次触发) web 应用上面 改变页面大小的统计 滚动页面位置的统计 输入框连续输入的请求次数控制 一开始,点击按钮,console.log('pay money') <body> <button id="btn">click&l

随机推荐