setTimeout()和setInterval()

函数的介绍

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时间后,再去调用,如果此时任务队列里面没有新的任务,那么很自然的按照理想的时间,他会调用,但是极端的情况下就不是那么如意了,如果时间到了,但是执行的任务队列里还堆积着任务,那么他将会被堆积着,直到前面的运行完毕,来一段代码

    var sleep = function (_sleepTime){
    var _curTime = new Date(),
        _nextTime;
    console.log("before sleep "+_curTime);
    while(!_nextTime || _nextTime - _curTime < _sleepTime){
        _nextTime = new Date();
    }
    console.log("after sleep "+_nextTime+"  last for "+(_nextTime-_curTime));};
    var time = function(){
        console.log("begin setTimeout block");
        sleep(100);
        console.log("end setTimeout block");
    };

    setTimeout(time,100);
    sleep(10000);

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

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

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

2.1 setInterval()

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

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

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


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

    var globle =0;
    var time3 = function(){
        console.log("I'm the No."+globle);
        globle++;
        sleep(1000);
    };
    setInterval(time3,2000);

看下console的情况

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

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

    var globle = 0 ,
        _limit = 5 ,
        _clear ;
    var time3 = function(){
        console.log("I'm the No."+globle);
        sleep(3000);
        globle++;
        if(globle > 5){
            clearInterval(_clear);
        }
    };
    _clear = setInterval(time3,100);

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

    I'm the No.0 
    before sleepFri May 23 2014 16:29:44 GMT+0800
    after sleep Fri May 23 2014 16:29:47 GMT+0800      last for 3000 
    I'm the No.1 
    before sleepFri May 23 2014 16:29:47 GMT+0800 
    after sleep Fri May 23 2014 16:29:50 GMT+0800      last for 3000 
    I'm the No.2 
    before sleepFri May 23 2014 16:29:50 GMT+0800
    after sleep Fri May 23 2014 16:29:53 GMT+0800      last for 3000 
    I'm the No.3 
    before sleepFri May 23 2014 16:29:53 GMT+0800 
    after sleep Fri May 23 2014 16:29:56 GMT+0800      last for 3000 
    I'm the No.4 
    before sleepFri May 23 2014 16:29:56 GMT+0800 
    after sleep Fri May 23 2014 16:29:59 GMT+0800      last for 3000 
    I'm the No.5 
    before sleepFri May 23 2014 16:29:59 GMT+0800 
    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)会被丢弃掉。确实很奇怪,下面用代码来测试下看看是否被丢弃掉

     var _beginTime ,
    _clear ,
    _globle = 0;

    var time4 = function(){
        if(_globle ==0){
            _beginTime = new Date();
        }
        console.log("I'm the No."+_globle);
        if(new Date() - _beginTime > 2000){
            clearInterval(_clear);
        }
        sleep(3000);
        _globle++;
    };
    _clear = setInterval(time4,100);

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

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

2.3 补充

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

    setTimeout(function () {
        //code
        setTimeout(arguments.callee, interval);
    }, interval)

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

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

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

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

  3. JavaScript Event Loop 浅析

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值