深入浅出理解JavaScript高级定时器原理与用法


Posted in Javascript onAugust 02, 2018

本文实例讲述了JavaScript高级定时器原理与用法。分享给大家供大家参考,具体如下:

setTimeout()setInterval()可以用来创建定时器,其基本的用法这里就不再做介绍了。这里主要介绍一下javascript的代码队列。在javascript中没有任何代码是立即执行的,一旦进程空闲则尽快执行。所以说定时器中设置的时间并不代表执行时间就一定相符,而是代表代码会在指定时间间隔后加入到队列中进行等待。如果在这个时间点上,队列中没有其他东西,那么这段代码就会被执行,表面上看上去好像代码就在精确指定的时间点上执行了。所以就会产生一些问题。

重复定时器

通常,我们使用setInterval方法来以相同时间间隔重复执行某段代码。但是使用该方法会有两个问题:第一个就是某些间隔会被跳过;第二个就是多个定时器的代码执行之间的间隔可能会比预期的小。

在这里,我们来举个例子:如果某个onclick事件处理程序使用setInterval设置了一个200ms间隔的重复定时器,如果事件处理程序花了300ms的时间完成,就会跳过一个时间间隔同时运行着一个定时器代码。

我们也可以通过下面的代码来得到结论:

//重复定时器
var i =0;
setInterval(function(){
 //如果事件处理时间长于间隔时间
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
},100);
//可以明显感觉到时间间隔不相等

为了避免这种时间间隔的问题,我们可以采用链式调用setTimeout方法来取代setInterval

//可以采用链式调用setTimeout来取代setInterval
var i = 0;
setTimeout(function(){
 //处理内容
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
 //
 setTimeout(arguments.callee,100);
},100);
//这样处理效果明显好多了。

每次函数执行的时候都会创建一个新的定时器,第二个setTimeout调用使用了arguments.callee来获取对当前执行的函数的引用,并为其设置另外一个定时器。这样做是为了在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔,也保证了在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行。可谓一举两得,现在主流框架中的动画一般都是这样来实现重复定时的。

函数节流

定时器不仅仅是用来定时的,也可以用来缓解浏览器的压力。浏览器中某些计算和处理要比其他的昂贵很多,比如说DOM操作,就会需要更多的内存和CPU时间,连续使用过多的DOM操作可能会导致浏览器挂起,甚至崩溃。

函数节流的基本思想就是,某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置一个。目的就是为了在执行函数的请求停止一段时间后再执行。

代码如下:

//再来谈谈函数节流
function throttle(method,context){
 clearTimeout(method.tId);
 method.tId = setTimeout(function(){
 method.call(context);
 },100);
}
//该函数接受两个参数,第一个是要执行的函数,第二个是作用域。
//使用方法demo
//未使用情况:
window.onresize = function(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
//使用情况;
function resizeDiv(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
window.onresize = function(){
 throttle(resizeDiv);
};
//只要代码是周期性执行的,都应该使用节流。

这样给用户的感觉并不会很大,确是给浏览器减少了不少的压力。函数节流也是很多框架常用的技巧之一。

demo示例:

//重复定时器
/*var i =0;
setInterval(function(){
 //如果事件处理时间长于间隔时间
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
},100);*/
//可以明显感觉到时间间隔不相等
//可以采用链式调用setTimeout来取代setInterval
/*var i = 0;
setTimeout(function(){
 //处理内容
 i++;
 for(var j=0;j<100000000;j++){}
 document.write(i+' ');
 //
 setTimeout(arguments.callee,100);
},100);*/
//这样处理效果明显好多了。
//以上就是重复定时器
//再来谈谈函数节流
function throttle(method,context){
 clearTimeout(method.tId);
 method.tId = setTimeout(function(){
 method.call(context);
 },100);
}
//该函数接受两个参数,第一个是要执行的函数,第二个是作用域。
//使用方法demo
//未使用情况:
window.onresize = function(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
//使用情况;
function resizeDiv(){
 var div = document.getElementByTagName(body);
 div.style.height = div.offsetWidth +'px';
}
window.onresize = function(){
 throttle(resizeDiv);
};
//只要代码是周期性执行的,都应该使用节流。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
Jun 02 Javascript
使用Meteor配合Node.js编写实时聊天应用的范例
Jun 23 Javascript
JavaScript类型系统之基本数据类型与包装类型
Jan 06 Javascript
JSON中key动态设置及JSON.parse和JSON.stringify()的区别
Dec 29 Javascript
Bootstrap实现提示框和弹出框效果
Jan 11 Javascript
node.js中实现kindEditor图片上传功能的方法教程
Apr 26 Javascript
AngularJs 终极购物车(实例讲解)
Nov 08 Javascript
微信小程序如何获取用户信息
Jan 26 Javascript
微信小程序url传参写变量的方法
Aug 09 Javascript
浅析vue-router原理
Oct 19 Javascript
JS回调函数原理与用法详解【附PHP回调函数】
Jul 20 Javascript
微信小程序实现底部弹出模态框
Nov 18 Javascript
解决vue router组件状态刷新消失的问题
Aug 01 #Javascript
Promise.all中对于reject的处理方法
Aug 01 #Javascript
详解es6超好用的语法糖Decorator
Aug 01 #Javascript
Vue Router去掉url中默认的锚点#
Aug 01 #Javascript
vue定义全局变量和全局方法的方法示例
Aug 01 #Javascript
node.js遍历目录的方法示例
Aug 01 #Javascript
深入浅出理解JavaScript闭包的功能与用法
Aug 01 #Javascript
You might like
discuz论坛 用户登录 后台程序代码
2008/11/27 PHP
ajax 的post方法实例(带循环)
2011/07/04 PHP
改写函数实现PHP二维/三维数组转字符串
2013/09/13 PHP
php判断数组元素中是否存在某个字符串的方法
2014/06/14 PHP
php简单实现短网址(短链)还原的方法(测试可用)
2016/05/09 PHP
PHP连续签到功能实现方法详解
2019/12/04 PHP
浅谈javascript 面向对象编程
2009/10/28 Javascript
js中判断文本框是否为空的两种方法
2011/07/31 Javascript
jquery 实现两级导航菜单附效果图
2014/03/07 Javascript
jQuery实现简单网页遮罩层/弹出层效果兼容IE6、IE7
2014/06/16 Javascript
JavaScript简单表格编辑功能实现方法
2015/04/16 Javascript
jQuery实现自动调整字体大小的方法
2015/06/15 Javascript
JS密码生成与强度检测完整实例(附demo源码下载)
2016/04/06 Javascript
一道优雅面试题分析js中fn()和return fn()的区别
2016/07/05 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
2016/12/15 Javascript
swiper 自动图片无限轮播实现代码
2018/05/21 Javascript
Koa日志中间件封装开发详解
2019/03/09 Javascript
vue实现新闻展示页的步骤详解
2019/04/11 Javascript
nodejs实现日志读取、日志查找及日志刷新的方法分析
2019/05/20 NodeJs
Python使用lxml模块和Requests模块抓取HTML页面的教程
2016/05/16 Python
Python+matplotlib+numpy绘制精美的条形统计图
2018/01/02 Python
python matplotlib 注释文本箭头简单代码示例
2018/01/08 Python
python接口自动化(十六)--参数关联接口后传(详解)
2019/04/16 Python
Django 迁移、操作数据库的方法
2019/08/02 Python
利用rest framework搭建Django API过程解析
2019/08/31 Python
Python实现投影法分割图像示例(二)
2020/01/17 Python
Html5游戏开发之乒乓Ping Pong游戏示例(二)
2013/01/21 HTML / CSS
关于责任的演讲稿
2014/05/20 职场文书
民生工作实施方案
2014/05/31 职场文书
小学国庆节活动方案策划书
2014/09/16 职场文书
《称赞》教学反思
2016/02/17 职场文书
Django项目配置Memcached和Redis, 缓存选择哪个更有优势
2021/04/06 Python
Java使用httpRequest+Jsoup爬取红蓝球号码
2021/07/02 Java/Android
用python基于appium模块开发一个自动收取能量的小助手
2021/09/25 Python
Eclipse+Java+Swing+Mysql实现电影购票系统(详细代码)
2022/01/18 Java/Android
mysql数据插入覆盖和时间戳的问题及解决
2022/03/25 MySQL