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 学习笔记二 字符串拼接
Mar 28 Javascript
struts2+jquery+json实现异步加载数据(自写)
Jun 24 Javascript
jquery foreach使用示例
Sep 12 Javascript
使用javascript实现页面定时跳转总结篇
Sep 21 Javascript
JS加jquery简单实现标签元素的显示或隐藏
Sep 23 Javascript
jquery实现的代替传统checkbox样式插件
Jun 19 Javascript
jQuery使用正则表达式限制文本框只能输入数字
Jun 18 Javascript
jQuery自定义元素右键点击事件(实现案例)
Apr 28 jQuery
jQuery获取table表中的td标签(实例讲解)
Jul 28 jQuery
从零开始实现Vue简单的Toast插件
Dec 03 Javascript
vue+导航锚点联动-滚动监听和点击平滑滚动跳转实例
Nov 13 Javascript
如何用vue实现网页截图你知道吗
Nov 17 Vue.js
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 删除一个目录及目录下的所有文件的函数代码
2010/05/26 PHP
谷歌音乐搜索栏的提示功能php修正代码
2011/05/09 PHP
php中url传递中文字符,特殊危险字符的解决方法
2013/08/17 PHP
一组PHP加密解密函数分享
2014/06/05 PHP
ThinkPHP关于session的操作方法汇总
2014/07/18 PHP
浅谈php+phpStorm+xdebug配置方法
2015/09/17 PHP
PHP实现根据时间戳获取周几的方法
2016/02/26 PHP
Ubuntu server 11.04安装memcache及php使用memcache来存储session的方法
2016/05/31 PHP
PHP数组内存利用率低和弱类型详细解读
2017/08/10 PHP
jQuery+CSS 实现的超Sexy下拉菜单
2010/01/17 Javascript
jQuery 表单验证扩展(四)
2010/10/20 Javascript
JavaScript中的匀速运动和变速(缓冲)运动详细介绍
2012/11/11 Javascript
node.js中的querystring.parse方法使用说明
2014/12/10 Javascript
jquery调取json数据实现省市级联的方法
2015/01/29 Javascript
Bootstrap面板学习使用
2017/02/09 Javascript
vue兄弟组件传递数据的实例
2018/09/06 Javascript
react写一个select组件的实现代码
2019/04/03 Javascript
微信小程序云开发 搭建一个管理小程序
2019/05/17 Javascript
vue+iview实现分页及查询功能
2020/11/17 Vue.js
JavaScript实现滑块验证解锁
2021/01/07 Javascript
[36:09]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.24
2019/09/10 DOTA
[01:18:45]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第三场2月1日
2021/03/11 DOTA
Python调用ctypes使用C函数printf的方法
2017/08/23 Python
Python实现的远程文件自动打包并下载功能示例
2019/07/12 Python
django ajax发送post请求的两种方法
2020/01/05 Python
Python实现图片查找轮廓、多边形拟合、最小外接矩形代码
2020/07/14 Python
Pycharm无法打开双击没反应的问题及解决方案
2020/08/17 Python
Html5移动端div固定到底部实现底部导航条的几种方式
2021/03/09 HTML / CSS
LivingSocial英国:英国本地优惠
2019/02/22 全球购物
红旗方阵解说词
2014/02/12 职场文书
小学科学教学计划
2015/01/21 职场文书
公司行政主管岗位职责
2015/04/09 职场文书
python文件名批量重命名脚本实例代码
2021/04/22 Python
MIME类型中application/xml与text/xml的区别介绍
2022/01/18 HTML / CSS
如何在Python中妥善使用进度条详解
2022/04/05 Python
windows系统搭建WEB服务器详细教程
2022/08/05 Servers