文章转自http://ejohn.org/blog/how-javascript-timers-work/
了解javascript定时器的工作是非常重要的,三个功能:
var id = setTimeout(fn, delay);
启动一个定时器延迟之后,该函数返回一个唯一的id,在一个以后的时间可以取消定时器。
var id = setInterval(fn, delay);
类似setTimeout的,但他不断调用这个函数(每一个延迟的时间),知道它被取消。
clearInterval(id);
clearTimeout(id);
接受一个计时器ID(返回的上述功能之一),并停止计时器回调的发生。
为了了解定时器的内部工作原理,有一个重要的概念需要探讨:定时器延迟没有保证。
因为Javascript代码是在一个单线程执行的异步事件。
执行的时候实在执行一个事件。
由于javascript永远只能在同一个时间执行一段代码(由于单线程的性质),代码快‘堵了’其他的异步事件。当一个异步事件发生,他被排队在稍后执行。
首先,第一个代码块内的javascript,启动两个定时器:一个10ms的setTimeout和一个10ms的setInterval。定时器在结束前就已经触发了第一块代码,然而,它不立即执行,因为线程。相反,延迟的函数开始排队,在下一个可用的时刻执行。
此外,我们看到鼠标点击出现在这第一个JavaScript块。这个异步事件(我们永远不知道什么时候用户可能会执行一个动作相关的JavaScript回调,因此它认为是异步)是不能被立即执行,因此,像最初的定时器,它正在排队等待稍后执行。
第一个代码块执行完后,浏览器会问:等待执行的是那个?在这种情况下,鼠标点击事件和定时器的回调等都在等待执行。然后浏览器选择一个(鼠标点击事件)并立即执行它。定时器将等到下一个可能的时间执行。
-
setTimeout(function(){
-
/* Some long block of code... */
-
setTimeout(arguments.callee, 10);
-
}, 10);
-
-
setInterval(function(){
-
/* Some long block of code... */
-
}, 10);
这两段代码是相同的功能,setTimeout回调执行后至少有一个10ms的延迟(很可能是更多的,但不会少)而setInterval将每10ms执行一个回调无论最后回调是否执行。
1.JavaScript引擎只有一个线程,迫使异步事件排队等待执行。
2.setTimeout和setInterval是如何执行异步代码根本不同的。
3.如果定时器立即执行是堵塞的,他将延迟到下一个可能的时间执行,(这个延迟长于预期的延迟)。
4.如果有足够长的时间来执行(比指定的延迟时间)间隔的执行连续无延迟。