js防抖和节流的深入讲解


Posted in Javascript onDecember 06, 2018

前言:

我们在做页面事件绑定的时候,经常要进行节流处理,比如鼠标异步点击,去执行一个异步请求时,需要让它在上一次没执行时不能再点击,又或者绑定滚动事件,这种持续触发进行dom判断的时候,就要按一定频率的执行。

本文主要给大家介绍了关于js防抖和节流的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧

0. 引入

首先举一个例子:

模拟在输入框输入后做ajax查询请求,没有加入防抖和节流的效果,这里附上完整可执行代码:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>没有防抖</title>
 <style type="text/css"></style>
 <script type="text/javascript">
 window.onload = function () {
 //模拟ajax请求
 function ajax(content) {
 console.log('ajax request ' + content)
 }
 let inputNormal = document.getElementById('normal');

 inputNormal.addEventListener('keyup', function (e) {
 ajax(e.target.value)
 })
 }
 </script>
</head>

<body>
 <div>
 1.没有防抖的输入:
 <input type="text" name="normal" id="normal">
 </div>
</body>

</html>

效果:在输入框里输入一个,就会触发一次“ajax请求”(此处是console)。

js防抖和节流的深入讲解

没有防抖和节流

缺点:浪费请求资源,可以加入防抖和节流来优化一下。

本文会分别介绍什么是防抖和节流,它们的应用场景,和实现方式。防抖和节流都是为了解决短时间内大量触发某函数而导致的性能问题,比如触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。但二者应对的业务需求不一样,所以实现的原理也不一样,下面具体来看看吧。

1. 防抖(debounce)

1.1 什么是防抖

在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时。

1.2 应用场景

(1) 用户在输入框中连续输入一串字符后,只会在输入完后去执行最后一次的查询ajax请求,这样可以有效减少请求次数,节约请求资源;

(2) window的resize、scroll事件,不断地调整浏览器的窗口大小、或者滚动时会触发对应事件,防抖让其只触发一次;

1.3 实现

还是上述列子,这里加入防抖来优化一下,完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入防抖</title>
 <style type="text/css"></style>
 <script type="text/javascript">
 window.onload = function () {
  //模拟ajax请求
  function ajax(content) {
  console.log('ajax request ' + content)
  }
  function debounce(fun, delay) {
  return function (args) {
   //获取函数的作用域和变量
   let that = this
   let _args = args
   //每次事件被触发,都会清除当前的timeer,然后重写设置超时调用
   clearTimeout(fun.id)
   fun.id = setTimeout(function () {
   fun.call(that, _args)
   }, delay)
  }
  }
  let inputDebounce = document.getElementById('debounce')
  let debounceAjax = debounce(ajax, 500)
  inputDebounce.addEventListener('keyup', function (e) {
  debounceAjax(e.target.value)
  })
 }
 </script>
</head>

<body>
 <div>
 2.加入防抖后的输入:
 <input type="text" name="debounce" id="debounce">
 </div>
</body>

</html>

代码说明:

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

2.只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行;

效果:

加入防抖后,当持续在输入框里输入时,并不会发送请求,只有当在指定时间间隔内没有再输入时,才会发送请求。如果先停止输入,但是在指定间隔内又输入,会重新触发计时。

js防抖和节流的深入讲解

加入防抖

2.节流(throttle)

2.1 什么是节流

规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

2.2 应用场景

(1)鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;

(2)在页面的无限加载场景下,需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据;

(3)监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;

2.3 实现

还是上述列子,这里加入节流来优化一下,完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <title>加入节流</title>
 <style type="text/css"></style>
 <script type="text/javascript">
 window.onload = function () {
  //模拟ajax请求
  function ajax(content) {
  console.log('ajax request ' + content)
  }

  function throttle(fun, delay) {
  let last, deferTimer
  return function (args) {
   let that = this;
   let _args = arguments;

   let now = +new Date();
   if (last && now < last + delay) {
   clearTimeout(deferTimer);
   deferTimer = setTimeout(function () {
    last = now;
    fun.apply(that, _args);
   }, delay)
   } else {
   last = now;
   fun.apply(that, _args);
   }
  }
  }
  let throttleAjax = throttle(ajax, 1000)
  let inputThrottle = document.getElementById('throttle')
  inputThrottle.addEventListener('keyup', function (e) {
  throttleAjax(e.target.value)
  })
 }
 </script>
</head>

<body>
 <div>
 3.加入节流后的输入:
 <input type="text" name="throttle" id="throttle">
 </div>
</body>

</html>

效果:实验可发现在持续输入时,会安装代码中的设定,每1秒执行一次ajax请求

js防抖和节流的深入讲解

加入节流

3. 小结

总结下防抖和节流的区别:

-- 效果:

函数防抖是某一段时间内只执行一次;而函数节流是间隔时间执行,不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

-- 原理:

防抖是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,都会清除当前的 timer 然后重新设置超时调用,即重新计时。这样一来,只有最后一次操作能被触发。

节流是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
又一个小巧的图片预加载类
May 05 Javascript
JavaScript 高级语法介绍
Jun 15 Javascript
使用PHP+JQuery+Ajax分页的实现
Apr 23 Javascript
在Firefox下js select标签点击无法弹出
Mar 06 Javascript
使用delegate方法为一个tr标签加一个链接
Jun 27 Javascript
深入理解JavaScript系列(36):设计模式之中介者模式详解
Mar 04 Javascript
如何高效率去掉js数组中的重复项
Apr 12 Javascript
谈谈Vue.js——vue-resource全攻略
Jan 16 Javascript
JS数组去重(4种方法)
Mar 27 Javascript
史上最全JavaScript数组去重的十种方法(推荐)
Aug 17 Javascript
angularJs利用$scope处理升降序的方法
Oct 08 Javascript
Node.js 多进程处理CPU密集任务的实现
May 26 Javascript
angular中两种表单的区别(响应式和模板驱动表单)
Dec 06 #Javascript
微信小程序dom操作的替代思路实例分析
Dec 06 #Javascript
详解Webstorm 下的Angular2.0开发之路(图文)
Dec 06 #Javascript
微信小程序实现通过js操作wxml的wxss属性示例
Dec 06 #Javascript
初探Vue3.0 中的一大亮点Proxy的使用
Dec 06 #Javascript
vue中v-for通过动态绑定class实现触发效果
Dec 06 #Javascript
vue通过指令(directives)实现点击空白处收起下拉框
Dec 06 #Javascript
You might like
PHP Cookie学习笔记
2016/08/23 PHP
PHP实现防止表单重复提交功能【基于token验证】
2018/05/24 PHP
laravel 判断查询数据库返回值的例子
2019/10/11 PHP
新闻内页-JS分页
2006/06/07 Javascript
javascript 播放器 控制
2007/01/22 Javascript
插件:检测javascript的内存泄漏
2007/03/04 Javascript
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
基于javascript制作微信聊天面板
2020/08/09 Javascript
jQuery控制div实现随滚动条滚动效果
2016/06/07 Javascript
AngularJS基础 ng-class-odd 指令示例
2016/08/01 Javascript
详解Javascript获取缓存和清除缓存API
2017/05/25 Javascript
JS表单提交验证、input(type=number) 去三角 刷新验证码
2017/06/21 Javascript
JavaScript 程序错误Cannot use 'in' operator to search的解决方法
2017/07/10 Javascript
Bootstrap + AngularJS 实现简单的数据过滤字符查找功能
2017/07/27 Javascript
微信小程序下拉刷新界面的实现
2017/09/28 Javascript
微信小程序上传图片到服务器实例代码
2017/11/07 Javascript
vue2 router 动态传参,多个参数的实例
2017/11/10 Javascript
JS实现图片上传多次上传同一张不生效的处理方法
2018/08/06 Javascript
js防抖和节流的深入讲解
2018/12/06 Javascript
JS实现根据数组对象的某一属性排序操作示例
2019/01/14 Javascript
ES6的异步操作之promise用法和async函数的具体使用
2019/12/06 Javascript
javascript 内存模型实例详解
2020/04/18 Javascript
python多线程threading.Lock锁用法实例
2014/11/01 Python
浅谈Django学习migrate和makemigrations的差别
2018/01/18 Python
Python实现的根据文件名查找数据文件功能示例
2018/05/02 Python
python解决字符串倒序输出的问题
2018/06/25 Python
用python求一重积分和二重积分的例子
2019/12/06 Python
Selenium基于PIL实现拼接滚动截图
2020/04/10 Python
联想韩国官网:Lenovo Korea
2018/05/10 全球购物
有趣的流行文化T恤、马克杯、手机壳和更多:Look Human
2019/01/07 全球购物
幼儿园教师培训方案
2014/02/04 职场文书
社团活动总结报告
2014/06/27 职场文书
新生儿未入户证明
2015/06/23 职场文书
结婚仪式主持词
2015/06/29 职场文书
导游词之泉州崇武古城
2019/12/20 职场文书
Java8中Stream的一些神操作
2021/11/02 Java/Android