Javascript的时间方法的内部机制

来源:互联网 发布:美工教学视频基础知识 编辑:程序博客网 时间:2024/04/30 15:47
原文:How JavaScript Timers Work

在基础层面上,学习javascript时间方法工作机制是很重要的。经常会遇到时间方法没有按照预期的运作,因为他们是运行在单一时间轴上的。我们先测试三个函数来创建和运作时间轴。

  • var id = setTimeout(fn, delay); – Initiates a single timer which will call the specified function after the delay. The function returns a unique ID with which the timer can be canceled at a later time.
  • var id = setInterval(fn, delay); – Similar to setTimeout but continually calls the function (with a delay every time) until it is canceled.
  • clearInterval(id);, clearTimeout(id); – Accepts a timer ID (returned by either of the aforementioned functions) and stops the timer callback from occurring.

为了更好的理解时间方法的内部运行机制,有个概念必须了解一下:延迟时间并不是能一直受到保证。由于所有在浏览器里的javascript都是单线程的,所以事件的执行一定是异步的,也就是说需要在一个队列中执行。有个很好的证明,下图


点击此处查看大图

这个假设图片中有很多信息可以挖掘,如果能完全理解这张图,你会对javascript的异步执行有更好的理解。这个图表模拟了我们的事件从上到下运行,单位是毫秒。蓝色的盒子展示了执行的javascript块。比如第一个第一个js块执行了18ms,鼠标点击模块大概执行了11ms。

由于javascript在同一时间只能执行一块代码,所以这些代码块对其他块是封闭的。这样意味着当一个异步的事件产生之后,会排队等待执行。不过如何排队因为浏览器的不同会不太一样,我们可以先把他简化。

开始的时候,执行第一个js块时,两个时间方法开始,一个参数是10ms的setTimeout和setinterval。方法的执行时间和位置就在我们完成第一块js代码之后。注意,代码块并不是马上执行的,延迟函数会排队等待下一个可以执行的时刻。

此外,我们在第一个代码块里看到了一个鼠标点击事件。Js回调函数相联系的这个异步事件(我们无法知道用户什么时候有动作,所以我们猜测它是异步的)并不能马上执行,就像最初的时间方法,先排队,再执行。

最初的js代码块执行之后,浏览器马上提出了一个问题:下一个要执行的是什么?在这个情况下,一个鼠标点击的句柄和一个时间方法的回调函数处于等待中。浏览器选择一个(鼠标点击事件句柄)然后马上执行。时间方法会等待下一个可执行的事件,然后执行。

注意,当鼠标点击事件句柄执行时,第一个interval回调函数也执行了。正如时间方法的句柄在排队等待下一个执行。然而,注意当时interval的时间间隔到了(事件方法句柄在执行),这个执行中的时间方法句柄就被丢弃了。就像是在连续执行一样。浏览器会一直执行到队列空了为止。

事实上,我们可以看到在这个情况下,第三个interval的时间间隔结束当这个回调函数还在执行。这里有一个很重要的事实,intervals 不管现在有没有在执行,都会排队,即时这样意味着时间延迟一点用都米有了。

最终,在第二个interval回调函数执行结束之后,我们可以看到什么都没有留下。这样意味着,浏览器现在在等待一个新的异步事件。我们获取这个异步事件在50ms标志处,然后inteval开始了。这时什么都没有阻塞他的执行,所以它马上开始

下面两段代码

setTimeout(function(){
/* Some long block of code… */
setTimeout(arguments.callee, 10);
}, 10);

setInterval(function(){
/* Some long block of code… */
}, 10);

这两款代码第一眼看起来表现的差不多,但是实际上不是。setTimeout会始终有10ms的延迟,在前一个回调函数执行结束之后。然后setintever会总是试图在10ms之后执行回调函数,即使回调函数还在执行。

我们总结为:

  • Javascript引擎是单线程的,强制要求异步事件排队等待执行。
  • Settimeout和setinterval 从在处理异步事件上就是很不一样的。
  • Interval在一些情况下(上面已经解释过,就是在延迟时间小于运行回调函数时间的时候),会连续的执行回调函数,就是说延迟时间神马的都浮云了。

我猜你也会喜欢这些o(∩_∩)o

  • 发现《javascript语言精粹》里闭包例子的一个小问题
  • (译)如何写出可维护的面向对象javascript
  • (转)豆瓣css开发规范
  • 用intellij idea搭建javascript开发环境
  • <[CDATA[是神马东西呢?
  • 一些最近看到的javascript相关数字
  • 关于javascript对象字面量小case
  • javascript作用域链之为什么说with影响性能
原创粉丝点击