在我们日常的开发中经常会用到一些容易被反复触发的事件。比如:scroll、resize、鼠标事件(mousemove,mouseover等)、键盘事件(keyup、keydown)。

频繁触发回调导致的大量计算会引发页面的抖动甚至卡顿。为了规避这种情况,我们需要一些手段来控制事件被触发的频率。就是在这样的背景下,throttle(事件节流)和 debounce(事件防抖)出现了。

“节流”与“防抖”的本质

这两个东西都以闭包的形式存在。

它们通过对事件对应的回调函数进行包裹、以自由变量的形式缓存时间信息,最后用 setTimeout 来控制事件的触发频率。

Debounce

防抖的概念其实是从机械开关和继电器的“去弹跳”(Debounce)衍生 出来的,基本思路就是把多个信号合并为一个信号。

手机拍照也有相似的概念,在拍照的时候手如果拿不稳晃的时候拍照,一般手机是拍不出好照片的,因此智能手机是在你按一下的时候连续拍许多张, 能过合成手段,生成一张,也就是我们平常说的HDR。翻译成JS就是,事件内的N个动作会被忽略,只有事件后由程序触发的动作才是有效的。

将目标方法(动作)包装在setTimeout里面,然后这个方法是一个事件的回调函数,如果这个回调一直连续执行,那么这些动作就一直不执行。为什么不执行呢,我们搞了一个clearTimeout,这样setTimeout里的方法就不会执行! 为什么要clearTimeout呢,我们就需要将事件内的连续动作删掉嘛!待到用户不触发这事件了。那么setTimeout就自然会执行这个方法。那么这个方法用在什么地方呢,就是用于input输入框架的格式验证,假如只是验证都是字母也罢了,太简单了,不怎么耗性能,如果是验证是否身份证,这性能消耗大,你可以隔170ms才验证一次,或者更长的时间。这时就需要这个东西。或者你这个是自动校验,需要将已有的输入数据往后端拉一个列表,频繁的交互,后端肯定耗不起,这时也需要这个,如隔350ms。下面我们来实际写一个防抖:

// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间function debounce(fn, delay) {  // 定时器  let timer = null

  // 将debounce处理结果当作函数返回  return function () {    // 保留调用时的this上下文    let context = this    // 保留调用时传入的参数    let args = arguments

    // 每次事件被触发时,都去清除之前的旧定时器,这里是闭包,timer变量必须清除    if(timer) {        clearTimeout(timer)    }    // 设立新定时器    timer = setTimeout(function () {      fn.apply(context, args)    }, delay)  }}

// 用debounce来包装scroll的回调const better_scroll = debounce(() => console.log('触发了滚动事件'), 1000)

document.addEventListener('scroll', better_scroll)

Throttle

节流的概念可以想象一下水坝,你建了水坝在河道中,不能让水流动不了,你只能让水流慢些。换言之,你不能让用户的方法都不执行。如果这样干,就是debounce了。为了让用户的方法在某个时间段内只执行一次,我们需要保存上次执行的时间点与定时器。下面来实际写一个节流:

// fn是我们需要包装的事件回调, interval是时间间隔的阈值        由于是闭包,last值可以保存上次的触发时间,不会重置为0if (now - last >= interval) {

用 Throttle 来优化 Debounce

debounce 的问题在于它“太有耐心了”。试想,如果用户的操作十分频繁——他每次都不等 debounce 设置的 delay 时间结束就进行下一次操作,于是每次 debounce 都为该用户重新生成定时器,回调函数被延迟了不计其数次。频繁的延迟会导致用户迟迟得不到响应,用户同样会产生“这个页面卡死了”的观感。

为了避免弄巧成拙,我们需要借力 throttle 的思想,打造一个“有底线”的 debounce——等你可以,但我有我的原则:delay 时间内,我可以为你重新生成定时器;但只要delay的时间到了,我必须要给用户一个响应。这个 throttle 与 debounce “合体”思路,已经被很多成熟的前端库应用到了它们的加强版 throttle 函数的实现中:

// fn是我们需要包装的事件回调, delay是时间间隔的阈值       timer = setTimeout(

如果觉得本文对你有所帮助,不如点个在看再走。

防抖 节流_防抖节流与前端性能优化相关推荐

  1. html修改原生checkbox选中的颜色_[三分钟小文]前端性能优化-HTML、CSS、JS部分

    阅读本文您将收获: 性能优化的整体思路 在HTML.CSS.JavaScript层级的性能优化 为什么要进行性能优化 用户: 提升用户体验,改善页面性能 开发者: 体现公司意志和开发人员技能 性能优化 ...

  2. 需要某个字体包才能正确显示此页面_[三分钟小文]前端性能优化-页面加载速度优化...

    本期内容请记住一个核心:JavaScript很快,DOM很慢 阅读本文您将收获: 从用户输入URL到看得到页面的过程 页面渲染过程 在页面加载层级的性能优化 用户看到页面之前都经历了什么 这一部分是面 ...

  3. 关于前端性能优化问题,认识网页加载过程和防抖节流

    前端性能优化-网页加载过程.性能优化方法.防抖和节流 一.网页加载过程 1.加载资源的形式 2.加载资源的过程 3.渲染页面的过程 4.关于window.onload 和 DOMContentLoad ...

  4. 前端性能优化之防抖-debounce

    这周接到一个需求-给输入框做模糊匹配.这还不简单,监听input事件,取到输入值去调接口不就行了? 然而后端小哥说不行,这个接口的数据量非常大,这种方式调用接口的频率太高,而且用户输入时调用根本没有必 ...

  5. 前端性能优化总结/懒加载、函数节流、优化dom操作、雪碧图、合并文件

    1.减少 HTTP 请求数量 在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信.浏览器与服务器需要经过三次握手,每次握手需要花费大量时间.而且不同浏览器对资源文件并发请求数量有限(不同浏览器 ...

  6. 前端服务器获取js文件偶尔慢_我所认识的前端性能优化

    现象: 用户体验差 网页太卡打不开(卡.慢) 服务器带宽流量(成本) 服务器压力 从哪处理:各处的缓存 地址缓存 减少DNS的解析请求.预解析DNS(不是"解析DNS") TCP缓 ...

  7. dll文件懒加载_前端性能优化

    # 前端性能优化 写在最前面:下面都是我对webpack的一些性能优化,想系统的学习性能优化方面的知识 推荐大家看看这本书 很系统 感觉面试也能如鱼得水 ## 构建优化 ### webpack优化 ( ...

  8. 前端白屏问题_前端性能优化之白屏时间

    前言 该篇文章会为您分享在前端性能优化中非常重要的一环-白屏时间,将从白屏时间的概念.重要性以及白屏的过程一一进行阐述,同时提供性能优化的策略与实践. 一.概念 白屏时间:即用户点击一个链接或打开浏览 ...

  9. 前端性能优化之Lazyload

    前端性能优化之Lazyload @(Mob前端-冬晨)[JavaScript|技术分享|懒加载] [TOC] Lazyload 简介 前端工作中,界面和效果正在变得越来越狂拽炫酷,与此同时性能也是不得 ...

  10. Web前端性能优化,应该怎么做?

    本文将分享一些前端性能优化的常用手段,包括减少请求次数.减小资源大小.各种缓存.预处理和长连接机制,以及代码方面的性能优化等方面. base64:尤其是在移动端,小图标可以base64(webpack ...

最新文章

  1. Metadata GC Threshold导致的full gc分析
  2. iOS应用安全之代码混淆实现篇
  3. 图的遍历:BFS和DFS
  4. java调度:(三)Timer中的单线程守护
  5. SpringMVC的请求-获得请求参数-获得基本类型参数
  6. mysql数据库导入导出_MySQL数据库导入导出详解
  7. debian修改密码
  8. 验证码——ImageIO.write的坑
  9. 【转】安卓开发经验分享:资源、UI、函数库、测试、构建一个都不能少
  10. 代码整洁之道-第5章-格式-读书笔记
  11. 【TWVRP】基于matlab遗传算法和模拟退火求解带时间窗自行车调度问题【含Matlab源码 370期】
  12. php连接云数据库语法,云水日记-PHP——连接数据库
  13. PanguVR获得400万种子轮融资,提供高效的VR家装解决方案
  14. JDK的Proxy技术实现AOP,InvocationHandler和Proxy详解——Spring AOP(三)
  15. Qt5.12安卓开发环境搭建
  16. 明星分分合合的洪荒点击量,微博Mesh服务化改造如何支撑?(附PPT下载)
  17. (转帖)微服务拆分的原则和方法(2)
  18. 把oblog3.13转换成PHP
  19. ios应用音频与来电铃声冲突问题
  20. 微信公众平台开发(56)优惠券

热门文章

  1. 微信公众号每次调用接口正确或错误的返回码
  2. eclipse svn不能忽略文件及文件夹,ignore设置无效 ?
  3. 3.hello hibernate
  4. java 数据库连接 释放_java - 数据库连接池耗尽 - Java - 堆栈内存溢出
  5. gitlab ci mysql_php-Gitlab CI:在阶段之间保留MySQL数据
  6. 如何让图片充满excel单元格_如何在Excel单元格建立下拉菜单
  7. python arima模型_Python时间序列处理之ARIMA模型的使用讲解
  8. ldo regula_使用C中的Regula Falsi方法找到复多项式方程的根
  9. agp模式_AGP的完整形式是什么?
  10. treeset java_Java TreeSet last()方法与示例