JS函数节流和函数防抖问题分析


Posted in Javascript onDecember 18, 2017

问题1:如果实现了dom拖拽功能,但是在绑定拖拽事件的时候发现每当元素稍微移动一点便触发了大量的回调函数,导致浏览器直接卡死,这个时候怎么办?

JS函数节流和函数防抖问题分析 

**问题2:**如果给一个按钮绑定了表单提交的post事件,但是用户有些时候在网络情况极差的情况下多次点击按钮造成表单重复提交,如何防止多次提交的发生?

为了应对如上场景,便出现了 函数防抖 和 函数节流 两个概念,总的来说:

这两个方法是在 时间轴上控制函数的执行次数。

函数防抖(debounce)

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

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

函数节流(throttle)

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

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

分析图

假设,我们观察的总时间为10秒钟,规定1秒作为一次事件的最小间隔时间。

如果触发事件的频率是 0.5s/次 ,那么函数防抖如图

JS函数节流和函数防抖问题分析 

因为始终没法等一秒钟就被再次触发了,所以最终没有一次事件是成功的。

函数节流如图

JS函数节流和函数防抖问题分析 

因为控制了最多一秒一次,频率为 0.5s/次 ,所以每一秒钟就有一次事件作废。最终控制成 1s/次

如果触发事件的频率是 2s/次 ,那么

函数防抖如图

JS函数节流和函数防抖问题分析 

因为 2s/次
已经大于了规定的最小时间,所以每计时两秒便触发一次。

函数节流如图

JS函数节流和函数防抖问题分析 

同样, 2s/次 大于了最小时间规定,所以每一次触发都生效。

应用场景

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

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

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

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

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

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

源码

函数防抖:

function debounce(fn, wait) {
 var timer = null;
 return function () {
  var context = this
  var args = arguments
  if (timer) {
   clearTimeout(timer);
   timer = null;
  }
  timer = setTimeout(function () {
   fn.apply(context, args)
  }, wait)
 }
}
var fn = function () {
 console.log('boom')
}
setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发,之后每1000ms触发一次
setInterval(debounce(fn,2000),1000) // 不会触发一次(我把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)

之所以返回一个函数,因为防抖本身更像是一个函数修饰,所以就做了一次函数柯里化。里面也用到了闭包,闭包的变量是 timer 。

函数节流

function throttle(fn, gapTime) {
 let _lastTime = null;
 return function () {
 let _nowTime = + new Date()
 if (_nowTime - _lastTime > gapTime || !_lastTime) {
  fn();
  _lastTime = _nowTime
 }
 }
}
let fn = ()=>{
 console.log('boom')
}
setInterval(throttle(fn,1000),10)

如图是实现的一个简单的函数节流,结果是 一秒打出一次boom

总结

以上所述是小编给大家介绍的JS函数节流和函数防抖问题分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript的面向对象(一)
Nov 09 Javascript
使用jQuery fancybox插件打造一个实用的数据传输模态弹出窗体
Jan 15 Javascript
extjs两个tbar问题探讨
Aug 08 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
Aug 17 Javascript
jQuery+Ajax+PHP弹出层异步登录效果(附源码下载)
May 27 Javascript
javascript数组对象常用api函数小结(连接,插入,删除,反转,排序等)
Sep 20 Javascript
Jquery针对tr td的一些实用操作方法(必看篇)
Oct 05 Javascript
详解如何使用vue-cli脚手架搭建Vue.js项目
May 19 Javascript
在微信小程序中保存网络图片
Feb 12 Javascript
更强大的vue ssr实现预取数据的方式
Jul 19 Javascript
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
Apr 15 Javascript
Vue如何基于es6导入外部js文件
May 15 Javascript
vue 将页面公用的头部组件化的方法
Dec 18 #Javascript
浅谈使用React.setState需要注意的三点
Dec 18 #Javascript
vue 项目如何引入微信sdk接口的方法
Dec 18 #Javascript
微信小程序实现给嵌套template模板传递数据的方式总结
Dec 18 #Javascript
微信小程序实现页面跳转传值以及获取值的方法分析
Dec 18 #Javascript
10个在JavaScript开发中常遇到的BUG
Dec 18 #Javascript
详解webpack与SPA实践之开发环境搭建
Dec 18 #Javascript
You might like
利用discuz自带通行证整合dedecms的方法以及文件下载
2007/03/06 PHP
php通过字符串调用函数示例
2014/03/02 PHP
php解析字符串里所有URL地址的方法
2015/04/03 PHP
Yii视图CGridView列表用法实例分析
2016/07/12 PHP
php版微信公众平台之微信网页登陆授权示例
2016/09/23 PHP
php如何把表单内容提交到数据库
2019/07/08 PHP
PHP过滤器 filter_has_var() 函数用法实例分析
2020/04/23 PHP
PHP如何通过带尾指针的链表实现'队列'
2020/10/22 PHP
一个JS小玩意 几个属性相加不能超过一个特定值.
2009/09/29 Javascript
基于jQuery的树控件实现代码(asp.net+json)
2010/07/11 Javascript
IE关闭时判断及AJAX注销案例学习
2013/02/18 Javascript
用示例说明filter()与find()的用法以及children()与find()的区别分析
2013/04/26 Javascript
JavaScript定时器详解及实例
2013/08/01 Javascript
javascript 函数及作用域总结介绍
2013/11/12 Javascript
自己使用jquery写的一个无缝滚动的插件
2014/04/30 Javascript
jQuery中prev()方法用法实例
2015/01/08 Javascript
详解jQuery简单的表单应用
2016/12/16 Javascript
详解NodeJs开发微信公众号
2018/05/25 NodeJs
微信小程序多音频播放进度条问题
2018/08/28 Javascript
vue-cli3.0配置及使用注意事项详解
2018/09/05 Javascript
JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法分析
2019/05/22 Javascript
layui监听单元格编辑前后交互的例子
2019/09/16 Javascript
jquery 时间戳转日期过程详解
2019/10/12 jQuery
微信小程序如何实现radio单选框单击打勾和取消
2020/01/21 Javascript
微信小程序换肤功能实现代码(思路详解)
2020/08/25 Javascript
[03:24]DOTA2超级联赛专访hao 大翻盘就是逆袭
2013/05/24 DOTA
python调用百度地图WEB服务API获取地点对应坐标值
2019/01/16 Python
Python面向对象总结及类与正则表达式详解
2019/04/18 Python
Python设置matplotlib.plot的坐标轴刻度间隔以及刻度范围
2019/06/25 Python
python flask中动态URL规则详解
2019/11/22 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
python GUI库图形界面开发之PyQt5时间控件QTimer详细使用方法与实例
2020/02/26 Python
英国现代绅士品牌:Hackett
2017/12/17 全球购物
行政专员岗位职责
2014/01/02 职场文书
协议书与合同的区别
2014/04/18 职场文书
2014年基建工作总结
2014/12/12 职场文书