setTimeout函数的神奇使用


Posted in Javascript onFebruary 26, 2017

【写在前面的胡言乱语】

自从大三开始实习之后,就没有写博客了,虽然学了很多东西,但是如果没有进行总结和分享,学的东西就很容易忘记,而且不进行分享,就不会手动去敲代码,这样对知识的理解就不够透彻。

现在毕业半年多了,最近学习了《JavaScript高级程序设计》这本书,受益匪浅,看了才知道虽然自己写了那么多JS,但是对JS的理解最多就只是中下水平。

现在看第二遍,边看边敲代码,边分享,希望看到这篇文章的你,能有所收获。

【这是正文】

《JavaScript高级程序设计》这本书里面,介绍了很多关于setTimeout函数的神奇使用,今天来介绍下第一个——使用setTimeout代替setInterval进行间歇调用。

书中是这么说的

“在开发环境下,很少使用间歇调用(setInterval),原因是后一个间歇调用很可能在前一个间歇调用结束前启动”。

这话怎么理解呢?

首先我们来看一下一般情况下的setInterval函数的使用,以及如何使用setTimeout代替setInterval

var executeTimes = 0;

var intervalTime = 500;

var intervalId = null;

 

// 放开下面的注释运行setInterval的Demo

intervalId = setInterval(intervalFun,intervalTime);

// 放开下面的注释运行setTimeout的Demo

// setTimeout(timeOutFun,intervalTime);

 

function intervalFun(){

executeTimes++;

console.log("doIntervalFun——"+executeTimes);

if(executeTimes==5){

clearInterval(intervalId);

}

}

 

function timeOutFun(){

executeTimes++;

console.log("doTimeOutFun——"+executeTimes);

if(executeTimes<5){

setTimeout(arguments.callee,intervalTime);

}

}

代码比较简单,我们只是在setTimeout的方法里面又调用了一次setTimeout,就可以达到间歇调用的目的。

重点来了,为什么作者建议我们使用setTimeout代替setInterval呢?setTimeout式的间歇调用和传统的setInterval间歇调用有什么区别呢?

区别在于,setInterval间歇调用,是在前一个方法执行前,就开始计时,比如间歇时间是500ms,那么不管那时候前一个方法是否已经执行完毕,都会把后一个方法放入执行的序列中。这时候就会发生一个问题,假如前一个方法的执行时间超过500ms,加入是1000ms,那么就意味着,前一个方法执行结束后,后一个方法马上就会执行,因为此时间歇时间已经超过500ms了。

书中没有给出代码证明这个结论,于是自己写了一段代码来验证。

var executeTimes = 0;

var intervalTime = 500;

var intervalId = null;

var oriTime = new Date().getTime();

 

// 放开下面的注释运行setInterval的Demo

intervalId = setInterval(intervalFun,intervalTime);

// 放开下面的注释运行setTimeout的Demo

// setTimeout(timeOutFun,intervalTime);

 

function intervalFun(){

executeTimes++;

var nowExecuteTimes = executeTimes;

var timeDiff = new Date().getTime() - oriTime;

console.log("doIntervalFun——"+nowExecuteTimes+", after " + timeDiff + "ms");

var delayParam = 0;

sleep(1000);

console.log("doIntervalFun——"+nowExecuteTimes+" finish !");

if(executeTimes==5){

clearInterval(intervalId);

}

}

 

function timeOutFun(){

executeTimes++;

var nowExecuteTimes = executeTimes;

var timeDiff = new Date().getTime() - oriTime;

console.log("doTimeOutFun——"+nowExecuteTimes+", after " + timeDiff + "ms");

var delayParam = 0;

sleep(1000);

console.log("doTimeOutFun——"+nowExecuteTimes+" finish !");

if(executeTimes<5){

setTimeout(arguments.callee,intervalTime);

}

}

 

function sleep(sleepTime){

var start=new Date().getTime();

while(true){

if(new Date().getTime()-start>sleepTime){


break;

}

}

}

(这里使用大牛提供的sleep函数来模拟函数运行的时间)

执行setInterval的Demo方法,看控制台

setTimeout函数的神奇使用

可以发现,fun2和fun1开始的间歇接近1000ms,刚好就是fun1的执行时间,也就意味着fun1执行完后fun2马上就执行了,和我们间歇调用的初衷背道而驰。

我们注释掉setInterval的Demo方法,放开setTimeout的Demo方法,运行,查看控制台

setTimeout函数的神奇使用

这下终于正常了,fun1和fun2相差了1500ms = 1000 + 500,fun2在fun1执行完的500ms后执行。

不知道你有没有和我一样脑洞大开,反正我是感觉视野又开阔了一点,setTimeout的妙用还有很多,下次接着聊!

Javascript 相关文章推荐
理解javascript中DOM事件
Dec 25 Javascript
Angular.js之作用域scope'@','=','&amp;'实例详解
Feb 28 Javascript
requirejs按需加载angularjs文件实例
Jun 08 Javascript
angularjs2 ng2 密码隐藏显示的实例代码
Aug 01 Javascript
Javascript中toFixed计算错误(依赖银行家舍入法的缺陷)解决方法
Aug 22 Javascript
详解webpack-dev-server使用http-proxy解决跨域问题
Jan 13 Javascript
解决iView中时间控件选择的时间总是少一天的问题
Mar 15 Javascript
React Form组件的实现封装杂谈
May 07 Javascript
JS如何获取地址栏的参数实例讲解
Oct 06 Javascript
解决vue组件中click事件失效的问题
Nov 09 Javascript
Vue使用鼠标在Canvas上绘制矩形
Dec 24 Vue.js
教你部署vue项目到docker
Apr 05 Vue.js
node.js入门学习之url模块
Feb 25 #Javascript
从零学习node.js之利用express搭建简易论坛(七)
Feb 25 #Javascript
从零学习node.js之express入门(六)
Feb 25 #Javascript
Node.JS中事件轮询(Event Loop)的解析
Feb 25 #Javascript
走进javascript——不起眼的基础,值和分号
Feb 24 #Javascript
angular.js 路由及页面传参示例
Feb 24 #Javascript
实例解析js中try、catch、finally的执行规则
Feb 24 #Javascript
You might like
php数据入库前清理 注意php intval与mysql的int取值范围不同
2010/12/12 PHP
laravel5实现微信第三方登录功能
2018/12/06 PHP
PHP获取ttf格式文件字体名的方法示例
2019/03/06 PHP
thinkPHP+mysql+ajax实现的仿百度一下即时搜索效果详解
2019/07/15 PHP
JavaScript 常见对象类创建代码与优缺点分析
2009/12/07 Javascript
基于jquery的自定义鼠标提示效果 jquery.toolTip
2010/11/14 Javascript
JS在textarea光标处插入文本的小例子
2013/03/22 Javascript
jQuery的slideToggle方法实例
2013/05/07 Javascript
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
JQuery中DOM事件绑定用法详解
2015/06/13 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
2015/08/17 Javascript
JavaScript实现的多种鼠标拖放效果
2015/11/03 Javascript
JavaScript的Backbone.js框架入门学习指引
2016/05/07 Javascript
微信小程序中button组件的边框设置的实例详解
2017/09/27 Javascript
javascript实现文本框标签验证的实例代码
2018/10/14 Javascript
详解vuex持久化插件解决浏览器刷新数据消失问题
2019/04/15 Javascript
Vue指令之 v-cloak、v-text、v-html实例详解
2019/08/08 Javascript
[01:00]DOTA2 store: Collection of Artisan's Wonders
2015/08/12 DOTA
不要用强制方法杀掉python线程
2017/02/26 Python
python发送邮件实例分享
2017/07/28 Python
图解python全局变量与局部变量相关知识
2019/11/02 Python
pytorch GAN伪造手写体mnist数据集方式
2020/01/10 Python
Python Tornado之跨域请求与Options请求方式
2020/03/28 Python
Python接口测试数据库封装实现原理
2020/05/09 Python
如何用Matlab和Python读取Netcdf文件
2021/02/19 Python
使用CSS3配合IE滤镜实现渐变和投影的效果
2015/09/06 HTML / CSS
浅谈关于html5中图片抛物线运动的一些心得
2018/01/09 HTML / CSS
three.js模拟实现太阳系行星体系功能
2019/09/03 HTML / CSS
美国地毯购买网站:Rugs USA
2019/02/23 全球购物
物业客服专员岗位职责
2013/11/30 职场文书
土木建筑学生自我评价
2014/01/14 职场文书
党风廉政承诺书
2014/03/27 职场文书
2014年结对帮扶工作总结
2014/12/17 职场文书
2016年社区“6.26”禁毒日宣传活动总结
2016/04/05 职场文书
一篇文章了解正则表达式的替换技巧
2022/02/24 Javascript