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

所属分类: 网络编程 / JavaScript 阅读数: 550
收藏 0 赞 0 分享

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

 

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

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

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

函数防抖(debounce)

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

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

函数节流(throttle)

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

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

分析图

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

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

 

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

函数节流如图

 

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

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

函数防抖如图

 

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

函数节流如图

 

同样, 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函数节流和函数防抖问题分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

浅谈Koa2框架利用CORS完成跨域ajax请求

这篇文章主要介绍了浅谈Koa2框架利用CORS完成跨域ajax请求,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

浅析Vue中method与computed的区别

在new Vue的配置参数中的computed和methods都可以处理大量的逻辑代码,但是什么时候用哪个属性,要好好区分一下才能做到正确的运用vue。这篇文章主要介绍了Vue中method与computed的区别,需要的朋友可以参考下
收藏 0 赞 0 分享

Vue2.0 http请求以及loading展示实例

下面小编就为大家分享一篇Vue2.0 http请求以及loading展示实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

轻松搞定jQuery+JSONP跨域请求的解决方案

了解了jsonp之后,大家应该也都明白了,jsonp主要就是用来实现跨域的获取数据,今天我们就来详细探讨下如何在实际中应用jsonp实现跨域
收藏 0 赞 0 分享

Vue2.0实现组件数据的双向绑定问题

这篇文章主要介绍了Vue2.0实现组件数据的双向绑定问题,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

node的process以及child_process模块学习笔记

这篇文章主要介绍了node的process以及child_process模块学习笔记,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

vue2.0 循环遍历加载不同图片的方法

下面小编就为大家分享一篇vue2.0 循环遍历加载不同图片的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

浅谈Vue2.0中v-for迭代语法的变化(key、index)

下面小编就为大家分享一篇浅谈Vue2.0中v-for迭代语法的变化(key、index),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

使用vue-aplayer插件时出现的问题的解决

这篇文章主要介绍了使用vue-aplayer插件时出现的问题的解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Element-ui table中过滤条件变更表格内容的方法

下面小编就为大家分享一篇Element-ui table中过滤条件变更表格内容的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多