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编程起步(第二课)
Feb 27 Javascript
javascript中的document.open()方法使用介绍
Oct 09 Javascript
HTML页面弹出居中可拖拽的自定义窗口层
May 07 Javascript
JavaScript Promise启示录
Aug 12 Javascript
浅谈JavaScript函数节流
Dec 09 Javascript
使用javascript实现Iframe自适应高度
Dec 24 Javascript
JS+CSS实现的竖向简洁折叠菜单效果代码
Oct 22 Javascript
jQuery基于muipicker实现仿ios时间选择
Feb 22 Javascript
利用JS对iframe父子(内外)页面进行操作的方法教程
Jun 15 Javascript
深入理解vue $refs的基本用法
Jul 13 Javascript
结合mint-ui移动端下拉加载实践方法总结
Nov 08 Javascript
layui 数据表格 根据值(1=业务,2=机构)显示中文名称示例
Oct 26 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
预告映像公开!第1章续篇剧场版动画《Princess Principal Crown Handler》4月10日上映!
2020/03/06 日漫
PHP基于yii框架实现生成ICO图标
2015/11/13 PHP
golang与PHP输出excel示例
2016/07/22 PHP
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
Prototype源码浅析 Number部分
2012/01/16 Javascript
JS字符串处理实例代码
2013/08/05 Javascript
node.js中的fs.symlinkSync方法使用说明
2014/12/15 Javascript
JavaScript实现SHA-1加密算法的方法
2015/03/11 Javascript
JS关闭窗口时产生的事件及用法示例
2016/08/20 Javascript
用vue和node写的简易购物车实现
2017/04/25 Javascript
Angular 4根据组件名称动态创建出组件的方法教程
2017/11/01 Javascript
ReactNative 之FlatList使用及踩坑封装总结
2017/11/29 Javascript
Angular实现搜索框及价格上下限功能
2018/01/19 Javascript
详解js删除数组中的指定元素
2018/10/31 Javascript
Vue页面渲染中key的应用实例教程
2021/01/12 Vue.js
wxPython事件驱动实例详解
2014/09/28 Python
使用python加密自己的密码
2015/08/04 Python
DataFrame中去除指定列为空的行方法
2018/04/08 Python
Python实现的从右到左字符串替换方法示例
2018/07/06 Python
使用Python实现一个栈判断括号是否平衡
2018/08/23 Python
详解Python并发编程之创建多线程的几种方法
2019/08/23 Python
Python-jenkins 获取job构建信息方式
2020/05/12 Python
Python内置方法和属性应用:反射和单例(推荐)
2020/06/19 Python
django form和field具体方法和属性说明
2020/07/09 Python
Python+OpenCV图像处理——实现轮廓发现
2020/10/23 Python
CSS3中box-shadow的用法介绍
2015/07/15 HTML / CSS
大众服装店创业计划书范文
2014/01/01 职场文书
会计学专业自荐信
2014/06/25 职场文书
白酒营销策划方案
2014/08/17 职场文书
设备收款委托书范本
2014/10/02 职场文书
合伙开公司协议书范本
2014/10/28 职场文书
2015年安全生产目标责任书
2015/01/29 职场文书
检讨书格式
2015/05/07 职场文书
2015小学五年级班主任工作总结
2015/05/21 职场文书
尊师重教主题班会
2015/08/14 职场文书
教你部署vue项目到docker
2022/04/05 Vue.js