当前位置:   article > 正文

setTimeout()和setInterval()_settimeout(begin())

settimeout(begin())

函数的介绍

1.1 setTimeout()

首先看下,这个函数的定义:(具体请见MDN)

    setTimeout(code,millisec);//在指定的延迟时间之后调用一个函数或者执行一个代码片段

函数的定义也说的很明白,他主要是在指定的时间之后运行一个函数,提前在这里指出一下,这个指定只是一个期望值,但不是一个实际的,实际他什么时候运行还是一个未知数,原因在下面会有介绍。

1.2 setInterval

函数的定义:(MDN)

    setInterval(codes, millisec);//周期性地调用一个函数(function)或者执行一段代码

有一个返回值是该函数的ID标识,可以用clearInterval函数来取消这样的周期执行

大概的作用就是周期行的调用一个函数,然后周期的话由millisec来决定,就是数学里的周期函数一样的概念,同理,他这个周期也是一个“期望值”,实际归实际。

参数millisec的介绍

在说之前首先推荐看下js定时器是如何工作的。推荐一个文章,How JavaScript Timers Work,如果英文看不明白的可以看下翻译版本how-javascript-timers-work翻译,看完估计你就会明白很多了,贴上一张里面的图js

我也稍微总结一下自己看的个人理解(如果不对希望能指出QQQ~~):js里面有以一个类似任务的队列,js是单线程的,在每一个时刻里面都只能执行一小段的代码,暂时理解为一个代码块,新的任务将会添加到尾巴上去,所以说任务是有先后的,然后当一个任务在执行的时候,纵然有另一个任务调用了,都必须需要等待到此刻代码块运行结束之后再调用。

2.1 setTimeout()

在前面提到了这个时间的参数定义的是js运行到setTimeout函数到他要执行这个函数的时间间隔,由于代码的执行效率是非常的高的,所有一般的情况下,我们是分辨不出这个中间的间隙。类似于setTimeout()这样的函数,执行的过程中,先将该任务放到执行队列中去,然后过了millisec时间后,再去调用,如果此时任务队列里面没有新的任务,那么很自然的按照理想的时间,他会调用,但是极端的情况下就不是那么如意了,如果时间到了,但是执行的任务队列里还堆积着任务,那么他将会被堆积着,直到前面的运行完毕,来一段代码

  1. var sleep = function (_sleepTime){
  2. var _curTime = new Date(),
  3. _nextTime;
  4. console.log("before sleep "+_curTime);
  5. while(!_nextTime || _nextTime - _curTime < _sleepTime){
  6. _nextTime = new Date();
  7. }
  8. console.log("after sleep "+_nextTime+" last for "+(_nextTime-_curTime));};
  9. var time = function(){
  10. console.log("begin setTimeout block");
  11. sleep(100);
  12. console.log("end setTimeout block");
  13. };
  14. setTimeout(time,100);
  15. sleep(10000);

再看下最后控制台的输出结果

  1. before sleep Fri May 23 2014 15:25:51 GMT+0800 (中国标准时间)
  2. after sleep Fri May 23 2014 15:26:01 GMT+0800 (中国标准时间) last for 10000
  3. begin setTimeout block
  4. before sleep Fri May 23 2014 15:26:01 GMT+0800 (中国标准时间)
  5. after sleep Fri May 23 2014 15:26:01 GMT+0800 (中国标准时间) last for 100
  6. end setTimeout block

分析下,按照正常的理想的状态,先执行的是setTimeout的函数,那么过了100ms之后应该会执行他,但是后面的一个sleep函数,直接执行了10000ms,虽然过了100ms确实需要去调用他,但是此时任务被阻塞了。所以你可以从上面的时间发现,setTimeout并没有按照期望的时间来执行。所以不能把有些任务太依赖于它

2.1 setInterval()

这个函数还是很有意思的一个,以前也没发现,也是看了那篇博客之后才发现。1.首先看一个比较正常的情况,比如你需要没过**时间间隔调用一个函数,就可以应用他

  1. var time2 = function(){
  2. console.log("sleep for 10ms");
  3. sleep(10);
  4. };
  5. setInterval(time2,1000);

很简单的情况,每个1秒调用一次


2.然后开始看一个情况,跟1差不多,不过是每隔两秒调用一次time3函数,每次跑time3函数要1秒中,代码如下

  1. var globle =0;
  2. var time3 = function(){
  3. console.log("I'm the No."+globle);
  4. globle++;
  5. sleep(1000);
  6. };
  7. setInterval(time3,2000);

看下console的情况

  1. I'm the No.0
  2. before sleepFri May 23 2014 16:19:04 GMT+0800
  3. after sleep Fri May 23 2014 16:19:05 GMT+0800 last for 1000
  4. I'm the No.1
  5. before sleepFri May 23 2014 16:19:06 GMT+0800
  6. after sleep Fri May 23 2014 16:19:07 GMT+0800 last for 1000
  7. I'm the No.2
  8. before sleepFri May 23 2014 16:19:08 GMT+0800
  9. after sleep Fri May 23 2014 16:19:09 GMT+0800 last for 1000

3.现在来一个执行时间要比间隔时间长的看看下情况 代码如下

  1. var globle = 0 ,
  2. _limit = 5 ,
  3. _clear ;
  4. var time3 = function(){
  5. console.log("I'm the No."+globle);
  6. sleep(3000);
  7. globle++;
  8. if(globle > 5){
  9. clearInterval(_clear);
  10. }
  11. };
  12. _clear = setInterval(time3,100);

主要的变化就是将time3函数的时间延长到3秒。这样就出现的时间的执行周期要比延迟的时间短的多多了,然后再来看下这回在console中的结果

  1. I'm the No.0
  2. before sleepFri May 23 2014 16:29:44 GMT+0800
  3. after sleep Fri May 23 2014 16:29:47 GMT+0800 last for 3000
  4. I'm the No.1
  5. before sleepFri May 23 2014 16:29:47 GMT+0800
  6. after sleep Fri May 23 2014 16:29:50 GMT+0800 last for 3000
  7. I'm the No.2
  8. before sleepFri May 23 2014 16:29:50 GMT+0800
  9. after sleep Fri May 23 2014 16:29:53 GMT+0800 last for 3000
  10. I'm the No.3
  11. before sleepFri May 23 2014 16:29:53 GMT+0800
  12. after sleep Fri May 23 2014 16:29:56 GMT+0800 last for 3000
  13. I'm the No.4
  14. before sleepFri May 23 2014 16:29:56 GMT+0800
  15. after sleep Fri May 23 2014 16:29:59 GMT+0800 last for 3000
  16. I'm the No.5
  17. before sleepFri May 23 2014 16:29:59 GMT+0800
  18. after sleep Fri May 23 2014 16:30:02 GMT+0800 last for 3000

不仔细看还不会发现,在每个执行的时间中,他的时间是连续的。并没有出现我们理想中时间的间隔100ms。中间的原因,可以这么来理解,当运行到第一个time3(1) 的时候,按照正常的情况执行,当时间过了100ms后,会再次调用time3(2),可此时,前一个time3(1)还在执行,不能打断,只能将time3(2)放到任务队列中,又过了10ms,按照老样子,又会调用time3(3),但是这个时候time3(1)还在执行,而time3(2)确还在任务队列中,这个时候就会发生一个比较奇怪的事情,就是time3(3)会被丢弃掉。确实很奇怪,下面用代码来测试下看看是否被丢弃掉

  1. var _beginTime ,
  2. _clear ,
  3. _globle = 0;
  4. var time4 = function(){
  5. if(_globle ==0){
  6. _beginTime = new Date();
  7. }
  8. console.log("I'm the No."+_globle);
  9. if(new Date() - _beginTime > 2000){
  10. clearInterval(_clear);
  11. }
  12. sleep(3000);
  13. _globle++;
  14. };
  15. _clear = setInterval(time4,100);

如果他是一味的将任务加到队列中,而没有进行丢弃的动作的话,周期是100ms,然后我做的限制是当执行时间超过2000ms后,清除定时,如果没丢弃那么队列中应该会有大概20个的动作等待操作,然后在看看console中的结果:

  1. I'm the No.0
  2. before sleep Sat May 24 2014 09:25:40 GMT+0800
  3. after sleep Sat May 24 2014 09:25:43 GMT+0800 last for 3000
  4. I'm the No.1
  5. before sleep Sat May 24 2014 09:25:43 GMT+0800 time.htm:14
  6. after sleep Sat May 24 2014 09:25:46 GMT+0800

2.3 补充

经过上面的一些分析之后,应该稍微对这俩函数有点了解1. setTimeout()执行的时间是>=规定的时间2. setInterval()执行的时间可能会比预期的时间小,比如上面例子中的0ms,没有时间间隔,某些间隔可能会被跳(被丢弃了)3. 如下代码

  1. setTimeout(function () {
  2. //code
  3. setTimeout(arguments.callee, interval);
  4. }, interval)

就是一个能防止中间间隔时间不出现那种0ms,或者是丢弃的方法,类似递归一样的解决

以上都是自己看博客加自己个人的理解,如有不对请指出,谢谢~再附上两篇参考的文章:

  1. setTimeout()和setInterval() 何时被调用执行

  2. setTimeout和setInterval的区别你真的了解吗?

  3. JavaScript Event Loop 浅析

  4. 理解JavaScript定时器:setTimeout和setInterval

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/610990
推荐阅读
相关标签
  

闽ICP备14008679号