Javascript的时间方法的内部机制
2011-11-21 14:17
155 查看
原文: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都是单线程的,所以事件的执行一定是异步的,也就是说需要在一个队列中执行。有个很好的证明,下图
![](http://hi.csdn.net/attachment/201111/21/0_1321856528upbm.gif)
点击此处查看大图
这个假设图片中有很多信息可以挖掘,如果能完全理解这张图,你会对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在一些情况下(上面已经解释过,就是在延迟时间小于运行回调函数时间的时候),会连续的执行回调函数,就是说延迟时间神马的都浮云了。
发现《javascript语言精粹》里闭包例子的一个小问题
(译)如何写出可维护的面向对象javascript
(转)豆瓣css开发规范
用intellij idea搭建javascript开发环境
<[CDATA[是神马东西呢?
一些最近看到的javascript相关数字
关于javascript对象字面量小case
javascript作用域链之为什么说with影响性能
在基础层面上,学习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都是单线程的,所以事件的执行一定是异步的,也就是说需要在一个队列中执行。有个很好的证明,下图
![](http://hi.csdn.net/attachment/201111/21/0_1321856528upbm.gif)
点击此处查看大图
这个假设图片中有很多信息可以挖掘,如果能完全理解这张图,你会对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影响性能
相关文章推荐
- (译)Javascript的时间方法的内部机制
- 【javascript笔记】 函数内部属性以及方法
- JavaScript输出当前时间Unix时间戳的方法
- js javascript 获取各种时间计算方法
- JavaScript关于时间的方法整理
- javascript 日期时间 转换的方法
- 使用Javascript动态创建表格,不同的方法,巨大的运行时间差异!
- JavaScript格式化日期时间的方法和自定义格式化函数示例
- javascript获取系统当前时间的方法
- JavaScript获取服务器端时间的方法
- JavaScript中用toString()方法返回时间为字符串
- 封装javascript帮助方法--时间转换
- javascript方法动态显示前一天与后一天日期时间
- String的subString()方法实现内部机制
- javascript显示动态时间的方法汇总
- JavaScript对象内联函数的使用,对象内部方法和属性的使用,以及事件冒泡的处理方式
- javascript中静态方法、实例方法、内部方法和原型的一点见解
- 【javascript笔记】 函数内部属性以及方法<三>
- python脚本设置超时机制系统时间的方法