JavaScript 函数节流详解及方法总结


Posted in Javascript onFebruary 09, 2017

JavaScript 函数节流详解

浏览器一个网页的UI线程只有一个,他同时会处理界面的渲染和页面JavaScript代码的执行(简单扩展一下,浏览器或者JavaScript运行大环境并不是单线程,诸如ajax异步回调、hybrid框架内与native通信、事件队列、CSS运行线程等等都属于多线程环境,不过ES6引入了Promise类来减少了部分异步情况)。因此当JavaScript代码运行计算量很大的方法时,就有可能阻塞UI线程,小则导致用户响应卡顿,严重的情况下浏览器会提示页面无响应是否强制关闭。例如网页的页面滚动事件、移动设备的滑动、缩放事件等。即使没有出现严重的性能问题,我们也应该站在性能优化的角度将短时间内会多次触发的大规模处理时间进行分流计算。

如何有效避免UI线程运行过长的代码,是所有用户交互应用需要考虑的问题,同样的问题在客户端Android可以使用UI主线程开子线程来分散计算。与此对应的,js也可以通过引入webWorker来分散计算,但是在js中有一个更简单并且效果不错的方法:函数节流。使用函数节流的核心技巧就是使用定时器分段计算。具体的实现方式大致有两种思路。

·方法一

1.这种实现方式的思路很好理解:设置一个一间隔时间,比如50毫秒,以此时间为基准设置定时器,当第一次触发事件到第二次触发事件间隔小于50毫秒时,清除这个定时器,并设置一个新的定时器,以此类推,直到有一次事件触发后50毫秒内没有重复触发。代码如下:

function debounce(method){ 
  clearTimeout(method.timer); 
  method.timer=setTimeout(function(){ 
   method(); 
  },50); 
}

这种设计方式有一个问题:本来应该多次触发的事件,可能最终只会发生一次。具体来说,一个循序渐进的滚动事件,如果用户滚动太快速,或者程序设置的函数节流间隔时间太长,那么最终滚动事件会呈现为一个很突然的跳跃事件,中间过程都被节流截掉了。这个例子举的有点夸张了,不过使用这种方式进行节流最终是会明显感受到程序比不节流的时候“更突兀”,这对于用户体验是很差的。有一种弥补这种缺陷的设计思路。

·方法二

2.第二种实现方式的思路与第一种稍有差别:设置一个间隔时间,比如50毫秒,以此时间为基准稳定分隔事件触发情况,也就是说100毫秒内连续触发多次事件,也只会按照50毫秒一次稳定分隔执行。代码如下:

var oldTime=new Date().getTime(); 
var delay=50; 
function throttle1(method){ 
  var curTime=new Date().getTime(); 
  if(curTime-oldTime>=delay){ 
   oldTime=curTime; 
   method(); 
  } 
}

相比于第一种方法,第二种方法也许会比第一种方法执行更多次(有时候意味着更多次请求后台,即更多的流量),但是却很好的解决了第一种方法清除中间过程的缺陷。因此在具体场景应根据情况择优决定使用哪种方法。

对于方法二,我们再提供另一种同样功能的写法:

var timer=undefined,delay=50; 
function throttle2(method){ 
  if(timer){ 
    return ; 
  } 
  method(); 
  timer=setTimeout(function(){ 
    timer=undefined; 
  },delay); 
}

最后说点个外话,说明一下函数节流的名称问题,大家往往会看到throttle和debounce两个方法名,throttle可以译为“节制,卡住”,debounce可以译为“防反跳”。在《JavaScript高级程序设计》中作者介绍了方法一,并且作者使用了“throttle”这个函数名。而在《第三方JavaScript编程》书中同时出现了方法一和方法二,作者将方法一命名为“debounce”,将方法二命名为“throttle”。国内在同时介绍两个方法的时候有些文章错误的将方法一命名为“throttle”,而将方法二命名为“debounce”,从英语的角度来说是很不负责任的。因此在这里拨乱反正:方法一适合理解为“防反跳”,应命名为“debounce”;方法二适合理解为“函数节制”,应命名为“throttle”。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
通过javascript设置css属性的代码
Dec 28 Javascript
Javascript Math ceil()、floor()、round()三个函数的区别
Mar 09 Javascript
基于jquery的模态div层弹出效果
Aug 21 Javascript
JavaScript常用基础知识强化学习
Dec 09 Javascript
使用three.js 画渐变的直线
Jun 05 Javascript
通过jsonp获取json数据实现AJAX跨域请求
Jan 22 Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
Feb 06 Javascript
详解Vue-axios 设置请求头问题
Dec 06 Javascript
Vue render函数实战之实现tabs选项卡组件
Apr 22 Javascript
使用JS判断页面是首次被加载还是刷新
May 26 Javascript
小程序click-scroll组件设计
Jun 18 Javascript
js实现跳一跳小游戏
Jul 31 Javascript
jQuery实现给input绑定回车事件的方法
Feb 09 #Javascript
jQuery分页插件jquery.pagination.js使用方法解析
Feb 09 #Javascript
Bootstrap面板学习使用
Feb 09 #Javascript
详解js的异步编程技术的方法
Feb 09 #Javascript
原生JS实现简单放大镜效果
Feb 08 #Javascript
基于JavaScript实现本地图片预览
Feb 08 #Javascript
js 判断登录界面的账号密码是否为空
Feb 08 #Javascript
You might like
php 需要掌握的东西 不做浮躁的人
2009/12/28 PHP
php 生成Tab键或逗号分隔的CSV
2016/09/24 PHP
又一个图片自动缩小的JS代码
2007/03/10 Javascript
十个优秀的Ajax/Javascript实例网站收集
2010/03/31 Javascript
ExtJs事件机制基本代码模型和流程解析
2010/10/24 Javascript
JS命名空间的另一种实现
2013/08/09 Javascript
$(document).ready(function() {})不执行初始化脚本
2014/06/19 Javascript
javascript进行四舍五入方法汇总
2014/12/16 Javascript
js实现下拉框选择要显示图片的方法
2015/02/16 Javascript
jQuery插件开发精品教程(让你的jQuery更上一个台阶)
2015/11/07 Javascript
基于JavaScript判断浏览器到底是关闭还是刷新(超准确)
2016/02/01 Javascript
详解Jquery实现ready和bind事件
2016/04/14 Javascript
基于bootstrap实现bootstrap中文网巨幕效果
2017/05/02 Javascript
收藏AngularJS中最重要的核心功能
2017/07/09 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
React Native 图片查看组件的方法
2018/03/01 Javascript
Vue递归实现树形菜单方法实例
2018/11/06 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
2019/01/30 Javascript
JavaScript实现指定数量的并发限制的示例代码
2020/03/10 Javascript
详解js中的几种常用设计模式
2020/07/16 Javascript
解决elementUI 切换tab后 el_table 固定列下方多了一条线问题
2020/07/19 Javascript
详解Vue 的异常处理机制
2020/11/30 Vue.js
uniapp微信小程序:key失效的解决方法
2021/01/20 Javascript
[46:00]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第一局
2016/03/03 DOTA
[01:04:08]完美世界DOTA2联赛PWL S3 INK ICE vs GXR 第一场 12.16
2020/12/18 DOTA
HTML中fieldset标签概述及使用方法
2013/02/01 HTML / CSS
阿迪达斯法国官方网站:adidas法国
2018/03/20 全球购物
斯洛伐克最大的婴儿食品和用品网上商店:Feedo.sk
2020/12/21 全球购物
职高毕业生自我鉴定
2013/10/21 职场文书
护士见习期自我鉴定
2014/02/08 职场文书
国旗下的演讲稿
2014/05/08 职场文书
星级党支部申报材料
2014/05/31 职场文书
物流管理专业推荐信
2014/09/06 职场文书
委托证明范本
2014/11/25 职场文书
学生早退检讨书(范文)
2019/08/19 职场文书
TV动画《间谍过家家》公开PV
2022/03/20 日漫