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 相关文章推荐
js常用排序实现代码
Dec 28 Javascript
利用jquery的获取JS文件中的字符串内容
Feb 14 Javascript
深入理解javascript原型链和继承
Sep 23 Javascript
JavaScript如何调试有哪些建议和技巧附五款有用的调试工具
Oct 28 Javascript
Perl Substr()函数及函数的应用
Dec 16 Javascript
js方法数据验证的简单实例
Sep 17 Javascript
bootstrap表单示例代码分享
May 18 Javascript
详解react-router4 异步加载路由两种方法
Sep 12 Javascript
Angular5升级RxJS到5.5.3报错:EmptyError: no elements in sequence的解决方法
Apr 09 Javascript
QQ跳转支付宝并自动领红包脚本(最新)
Jun 22 Javascript
ES6中Set和Map用法实例详解
Mar 02 Javascript
Vue自定义全局弹窗组件操作
Aug 11 Javascript
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
我的论坛源代码(二)
2006/10/09 PHP
php跨站攻击实例分析
2014/10/28 PHP
Thinkphp中volist标签mod控制一定记录的换行BUG解决方法
2014/11/04 PHP
Yii框架获取当前controlle和action对应id的方法
2014/12/03 PHP
php写入文件不覆盖的实例讲解
2019/09/17 PHP
EasyUI,点击开启编辑框,并且编辑框获得焦点的方法
2015/03/01 Javascript
javascript实现通过表格绘制颜色填充矩形的方法
2015/04/21 Javascript
jquery.validate表单验证插件使用详解
2017/06/21 jQuery
weex里Vuex state使用storage持久化详解
2017/09/09 Javascript
基于vue的短信验证码倒计时demo
2017/09/13 Javascript
javaScript和jQuery自动加载简单代码实现方法
2017/11/24 jQuery
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
2018/09/04 Javascript
vue19 组建 Vue.extend component、组件模版、动态组件 的实例代码
2019/04/04 Javascript
前后端常见的几种鉴权方式(小结)
2019/08/04 Javascript
vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
2021/02/20 Vue.js
[01:06:54]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第一场 1月24日
2021/03/11 DOTA
python 计算两个日期相差多少个月实例代码
2017/05/24 Python
Python IDLE入门简介
2017/12/08 Python
python类的方法属性与方法属性的动态绑定代码详解
2017/12/27 Python
利用Opencv中Houghline方法实现直线检测
2018/02/11 Python
python实现NB-IoT模块远程控制
2018/06/20 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
python 叠加等边三角形的绘制的实现
2019/08/14 Python
OpenCV4.1.0+VS2017环境配置的方法步骤
2020/07/09 Python
白兰氏健康Mall:BRAND’S
2017/11/13 全球购物
法院实习人员自我鉴定
2013/09/26 职场文书
高三家长寄语
2014/04/03 职场文书
幼师求职信
2014/06/23 职场文书
2015年教师自我评价范文
2015/03/04 职场文书
社区法制宣传月活动总结
2015/05/07 职场文书
航班延误投诉信
2015/07/02 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
react 项目中引入图片的几种方式
2021/06/02 Javascript
MySQL系列之一 MariaDB-server安装
2021/07/02 MySQL
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python
Java中的继承、多态以及封装
2022/04/11 Java/Android