从基础的层面来讲,理解JavaScript的定时器是如何工作的是非常重要的。计时器的执行常常和我们的直观想象不同,那是因为JavaScript引擎是单线程的。我们先来认识一下下面三个函数是如何控制计时器的。
-
var id = setTimeout(fn, delay);
- 初始化一个计时器,然后在指定的时间间隔后执行。该函数返回一个唯一的标志ID(Number类型),我们可以使用它来取消计时器。 -
var id = setInterval(fn, delay);
- 和setTimeout有些类似,但它是连续调用一个函数(时间间隔是delay参数)直到它被取消。 -
clearInterval(id);
,clearTimeout(id);
- 使用计时器ID(setTimeout 和 setInterval的返回值)来取消计时器回调的发生
为了理解计时器的内在执行原理,有一个重要的概念需要加以探讨:计时器的延迟(delay)是无法得到保障的。由于所有JavaScript代码是在一个线程里执行的,所有异步事件(例如,鼠标点击和计时器)只有拥有执行机会时才会执行。用一个很好的图表加以说明:
(点击查看大图)
在这个图表中有许多信息需要理解,如果完全理解了它们,你会对JavaScript引擎如何实现异步事件有一个很好的认识。这是一个一维的图标:垂直方向表示时间,蓝色的区块表示JavaScript代码执行块。例如第一个JavaScript代码执行块需要大约18ms,鼠标点击所触发的代码执行块需要11ms,等等。
由于JavaScript引擎同一时间只执行一条代码(这是由于JavaScript单线程的性质),所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。这就意味着当一个异步事件发生(例如,鼠标点击,计时器被触发,或者Ajax异步请求)后,这些事件的回调函数将排在执行队列的最后等待执行(实际上,排队的方式根据浏览器的不同而不同,所以这里只是一个简化);
从第一个JavaScript执行块开始研究,在第一个执行块中两个计时器被初始化:一个10ms的setTimeout()
和一个10ms的setInterval()
。依据何时何地计时器被初始化(计时器初始化完毕后就会开始计时),计时器实际上会在第一个代码块执行完毕前被触发。但是,计时器上绑定的函数不会立即执行(不被立即执行的原因是JavaScript是单线程的)。实际上,被延迟的函数将依次排在执行队列的最后,等待下一次恰当的时间再执行。
此外,在第一个JavaScript执行块中我们看到了一个“鼠标点击”事件发生了。一个JavaScript回调函数绑定在这个异步事件上了(我们从来不知道用户什么时候执行这个(点击)事件,因此认为它是异步的),这个函数不会被立即执行,和上面的计时器一样,它将排在执行队列的最后,等待下一次恰当的时候执行。
当第一个JavaScript执行块执行完毕后,浏览器会立即问一个问题:哪个函数(语句)在等待被执行?在这时,一个“鼠标点击事件处理函数”和一个“计时器回调函数”都在等待执行。浏览器会选择一个(实际上选择了“鼠标点击事件的处理函数”,因为由图可知它是先进队的)立即执行。而“计时器回调函数”将等待下次适合的时间执行。
注意,当“鼠标点击事件处理函数”执行的时候,setInterval
的回调函数第一次被触发了。和setTimeout
的回调函数一样,它将排到执行队列的最后等待执行。但是,一定要注意这一点:当setInterva
l回调函数第二次被触发时(此时setTimeout
函数仍在执行)setTimeout
的第一次触发将被抛弃掉。当一个很长的代码块在执行时,可能把所有的setInterval
回调函数都排在执行队列的后面,代码块执行完之后,结果便会是一大串的setInterval回调函数等待执行,并且这些函数之间没有间隔,直到全部完成。所以,浏览器倾向于的当没有更多interval
的处理函数在排队时再将下一个处理函数排到队尾(这是由于间隔的问题)。
我们能够发现,当第三个setInterval
回调函数被触发时,之前的setInterval回调函数仍在执行。这就说明了一个很重要的事实:setInterval
不会考虑当前正在执行什么,而把所有的堵塞的函数排到队列尾部。这意味着两次setInterval回调函数之间的时间间隔会被牺牲掉(缩减)。
最后,当第二个setInterval
回调函数执行完毕后,我们可以看到没有任何程序等待JavaScript引擎执行了。这就意味着浏览器现在在等待一个新的异步事件的发生。在50ms时一个新的setInterval
回调函数再次被触发,这时,没有任何的执行块阻塞它的执行了。所以它会立刻被执行。
让我们用一个例子来阐明setTimeout
和setInterval
之间的区别:
/* Some long block of code... */
setTimeout(arguments.callee, 10);
}, 10);
setInterval(function(){
/* Some long block of code... */
}, 10);
这两句代码乍一看没什么差别,但是它们是不同的。setTimeout回调函数的执行和上一次执行之间的间隔至少有10ms(可能会更多,但不会少于10ms),而setInterval的回调函数将尝试每隔10ms执行一次,不论上次是否执行完毕。
在这里我们学到了很多知识,总结一下:
- JavaScript引擎是单线程的,强制所有的异步事件排队等待执行
-
setTimeout
和setInterval
在执行异步代码的时候有着根本的不同 - 如果一个计时器被阻塞而不能立即执行,它将延迟执行直到下一次可能执行的时间点才被执行(比期望的时间间隔要长些)
- 如果
setInterval
回调函数的执行时间将足够长(比指定的时间间隔长),它们将连续执行并且彼此之间没有时间间隔。
上述这些知识点都是非常重要的。了解了JavaScript引擎是如何工作的,尤其是大量的异步事件(连续)发生时,才能为构建高级应用程序打好基础。
原文链接 http://www.phpweblog.net/rainman/archive/2009/01/05/6267.html
相关推荐
base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz
JavaScript中的编码和转义函数主要有encodeURI、encodeURIComponent和escape这三个函数,它们用于处理URL和URI中的特殊字符。下面将详细介绍这三个函数的功能和使用场景。 首先,encodeURI函数的主要用途是编码整个...
现代通信原理考试试题zz现代通信原理考试试题zz
在本篇文章中,我们将深入探讨如何利用5152单片机与Proteus软件结合,在定时器T0中断的基础上实现长时间定时的功能。...这不仅有助于加深对单片机定时器工作原理的理解,也为进一步探索其他高级功能奠定了坚实的基础。
#### 定时器工作原理 在单片机中,定时器主要用于产生周期性的中断或者测量时间间隔。通过配置定时器的预分频器、比较寄存器等参数,可以精确地控制定时器的溢出时间,进而实现不同频率和占空比的PWM波形输出。 ###...
《深入理解CString的工作原理》 cstring,作为Microsoft MFC库中的重要成员,是C++对标准C字符串的封装,旨在解决C语言中字符串处理带来的诸多问题,如缓冲溢出和内存泄漏。这篇文章将深入探讨CString的工作原理,...
综上所述,“8051 Proteus 仿真 C 源码定时器控制数码动态显示”这一知识点涵盖了 8051 微控制器的基础知识、Proteus 仿真的使用方法、C 语言编程技巧、定时器的工作原理以及数码动态显示技术的应用等多个方面。...
根据给定文件的信息,我们可以提炼出以下几个核心知识点:5152单片机的基本概念、Proteus软件的使用、定时器T1的工作原理及应用、查询方式在定时器中的运用以及如何通过单片机发出1KHz音频信号。 ### 一、5152...
2. **番茄工作法**:这种方法使用定时器将工作划分为25分钟的工作块,每个工作块后休息5分钟,四个工作块后长休15分钟。这种分割工作和休息的方式有助于保持专注并防止疲劳。 3. **敏捷开发中的时间管理**:敏捷...
这不仅包括了如何利用5152单片机及其仿真软件Proteus来实现一个简单的门铃系统,还包括了具体的编程和调试方法,以及如何通过定时器来控制门铃的响铃时间和间隔。 ### 一、5152单片机简介 5152单片机实际上是指...
8051内置有两个16位的定时器/计数器,即T0和T1,每个定时器都具有多种工作模式,可以通过设置相关的寄存器来配置。定时器的工作模式包括: - **模式0**:13位定时器/计数器。 - **模式1**:16位定时器/计数器。 - **...
1. **设置定时器工作模式**:通常选择模式1或模式2,根据不同的需求选择合适的工作模式。 2. **初始化定时器初值**:根据所选模式计算出合适的初始值,以达到所需的定时时间。 3. **使能中断**:打开定时器中断,并...
2. **定时器配置**:设置定时器的工作模式、预置值等参数,以满足音乐播放所需的定时精度。 3. **音乐数据存储**:将音乐数据以适当格式存储在程序存储器中。 4. **播放逻辑**:根据当前状态(如按键输入、定时器...
Proteus是一款强大的电路设计与仿真软件,能够支持电路原理图的设计、PCB板的设计以及单片机程序的调试等功能。它主要由两部分组成: 1. **ISIS**:用于绘制电路原理图。 2. **ARES**:用于PCB设计布局。 Proteus...
ZZ561401.CAB ZZ561401.CAB ZZ561401.CAB
《zz809.com留言本》是一款基于网络的互动交流平台,源于柏图留言本BTB 1.2版本,并经过管理员zz809的定制和优化。...通过下载和研究这个源码,我们可以深入理解网络留言系统的构建原理,提升自己的编程能力。
ATmega16拥有16KB的系统内可编程Flash、512字节的EEPROM、1KB的SRAM、32个通用I/O口线、32个通用工作寄存器、四个灵活的定时器/计数器、两个串行 USART、一个可编程的串行接口、一个具有比较模式的16位定时器、片上...
此项目不仅能够帮助初学者更好地理解单片机的工作原理,还能够提升他们在实际应用中的编程技巧。 #### 一、项目背景及意义 随着科技的发展,单片机已经成为自动化领域不可或缺的一部分。5152单片机作为一种经典的8...
8051 微控制器的核心包括一个 CPU、RAM、ROM(或闪存)、定时器/计数器、串行通信接口以及 I/O 口等。 #### 知识点二:Proteus 仿真软件概述 Proteus 是一种用于电路设计和仿真的软件工具。该软件由 Labcenter ...
wincc SIMATIC WinCC是第一个使用最新的32位技术的过程监视系统,具有良好的开放性和灵活性。 从面市伊始,用户就对SIMATIC WinCC印象深刻。