SetTimeout和setInterval是大家肯定都很熟悉的两个函数,但可能并不是每个用过这两种方法的人都知道它们的内在本质。
将两个实现定时调用的函数理解为类似线程的东西可能是错误的。似乎被调用的函数将在一个时间片内并发执行,但事实并非如此。实际情况是javascript以单线程的方式运行在浏览器的javascript引擎中。setTimeout和setInterval的作用是在你设定的时间,把你要执行的代码插入到js engine维护的代码队列中。插入代码队列并不意味着您的代码会立即执行。理解这一点很重要。而且,setTimeout和setInterval有点不一样。
先谈谈setTimeout
复制代码代码如下:函数click () {//codeblock1.settimeout(function(){//process.}, 200);//code block2}假设我们将这个方法绑定到一个按钮的onclick事件。当我们按下按钮时,一定会先执行block1的内容,然后运行到setTimeout的地方。setTimeout会告诉浏览器,200ms后我会在你的队列中插入一段要执行的代码’,当然浏览器同意了(注意,插入代码并不代表马上执行)。setTimeout代码运行后,紧接着的block2代码开始执行。这里,问题就开始说明了。如果block2代码的执行时间超过200ms,会有什么结果?可能按照你之前的理解,你会想当然的认为只要200ms一到,你的进程代码就会马上执行.事实是,在block2的执行过程中(200ms之后),进程代码被插入到代码队列中,但是你要等到click方法完成之后,进程代码段才被执行。从代码队列来看,click之后是进程代码,js是单线程方式执行的,应该不难理解。如果是另一种情况,block2代码的执行时间是200ms,setTimeout在200ms后将进程代码插入代码队列,而当时执行线程可能已经空闲,结果是200ms后将进程代码插入队列并立即执行,这让你感觉200ms后,刚刚执行了.再看看setInterval
。这里可能有两个问题:1。可以跳过该时间间隔。2.可能定期调用的代码的执行时间复制如下:function click () {/codeblock1.setinterval(function(){//进程.}, 200);//代码块2 }如上,我们假设通过一次点击,setInterval被触发每隔一个时间段执行进程代码。
比如onclick需要300ms完成执行,block1代码完成执行,setInterval以5ms为时间点。205ms,插入进程代码,点击代码平滑结束,进程代码开始执行(相当于图中的定时器代码)。但是进程代码已经执行了比较长的时间,超过了下一个插入时间点405ms,这样在代码队列之后又插入了一个进程代码,进程继续执行,超过了插入时间点605ms。问题来了。也许你会认为在代码队列之后会插入另一个流程代码.真相是,由于代码队列中已经有一个未执行的进程代码,605ms的插入时间会被无情地跳过,因为js引擎中只允许有一个未执行的进程代码,不知道你会不会恍然大悟。
对于这种情况,可以将代码以更好的代码形式复制如下:SetTimeout(function(){//processing SetTimeout(arguments . callee,interval);},区间);
估计稍微想了一下这个就明白优点了,这样就不会有时间点被跳过的问题了。希望能有所帮助。可能我不是很清楚。如果我觉得自己英语基础不错,可以直接看。
关于高级定时器部分,个人觉得这本书真的很不错。无论是想从头学起,还是平日里无事可做,翻翻参考都是很不错的。作者是雅虎一个牛逼的前端开发工程师:)