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 相关文章推荐
捕获关闭窗口的脚本
Jan 10 Javascript
js/html光标定位的实现代码
Sep 23 Javascript
鼠标滚轴控制文本框值的JS代码
Nov 19 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
May 29 Javascript
Javascript字符串常用方法详解
Jul 21 Javascript
原生Javascript和jQuery做轮播图简单例子
Oct 11 Javascript
vue.js实现用户评论、登录、注册、及修改信息功能
May 30 Javascript
SelectPage v2.4 发布新增纯下拉列表和关闭分页功能
Sep 07 Javascript
[原创]js实现保存文本框内容为本地文件兼容IE,chrome,火狐浏览器
Feb 14 Javascript
Vue 与 Vuex 的第一次接触遇到的坑
Aug 16 Javascript
BootstrapValidator验证用户名已存在(ajax)
Nov 08 Javascript
解决Vue在Tomcat8下部署页面不加载的问题
Nov 12 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 zlib扩展实现页面GZIP压缩输出
2010/06/17 PHP
再Docker中架设完整的WordPress站点全攻略
2015/07/29 PHP
PHP实用小技巧之调用录像的方法
2019/12/05 PHP
Jquery截取中文字符串的实现代码
2010/12/22 Javascript
JavaScript中“+”的陷阱深刻理解
2012/12/04 Javascript
12种不宜使用的Javascript语法整理
2013/11/04 Javascript
js动态修改input输入框的type属性(实现方法解析)
2013/11/13 Javascript
javascript实现选中复选框后相关输入框变灰不可用的方法
2015/08/11 Javascript
Vue filters过滤器的使用方法
2017/07/14 Javascript
浅谈Angular 中何时取消订阅
2017/11/22 Javascript
Vue匿名插槽与作用域插槽的合并和覆盖行为
2019/04/22 Javascript
vscode中eslint插件的配置(prettier配置无效)
2019/09/10 Javascript
jQuery Raty星级评分插件使用方法实例分析
2019/11/25 jQuery
在vue中使用axios实现post方式获取二进制流下载文件(实例代码)
2019/12/16 Javascript
JS实现简易留言板(节点操作)
2020/03/16 Javascript
在Vue 中获取下拉框的文本及选项值操作
2020/08/13 Javascript
google广告之另类js调用实现代码
2020/08/22 Javascript
[25:45]2018DOTA2亚洲邀请赛4.5SOLO赛 Sylar vs Paparazi
2018/04/06 DOTA
使用Python中的cookielib模拟登录网站
2015/04/09 Python
Python入门_浅谈字符串的分片与索引、字符串的方法
2017/05/16 Python
python模块之time模块(实例讲解)
2017/09/13 Python
python selenium 获取标签的属性值、内容、状态方法
2018/06/22 Python
django主动抛出403异常的方法详解
2019/01/04 Python
Python 变量的创建过程详解
2019/09/02 Python
Django DRF认证组件流程实现原理详解
2020/08/17 Python
Python文件名匹配与文件复制的实现
2020/12/11 Python
html5指南-2.如何操作document metadata
2013/01/07 HTML / CSS
html5实现图片转圈的动画效果——让页面动起来
2017/10/16 HTML / CSS
文化宣传方案
2014/03/13 职场文书
心理健康活动总结
2014/04/30 职场文书
环保倡议书范文
2014/05/12 职场文书
反洗钱宣传活动总结
2014/08/26 职场文书
2014年英语工作总结
2014/12/20 职场文书
初中作文评语集锦
2014/12/25 职场文书
《玩出了名堂》教学反思
2016/02/17 职场文书
启迪人心的励志语录:脾气永远不要大于本事
2020/01/02 职场文书