解读javascript的计时器(翻译教程)(2)

http://www.itjxue.com  2015-08-06 23:10  来源:未知  点击次数: 

既然javascript在一定时间内之执行一部分代码(源于单线程的特性),那么这些代码块的每一个就被封锁在其它异步事件执行的进程中。这表明当一个异步事件发生时(如鼠标点击、计时器释放、XMLHttpRequest请求完成),它将排队等候执行(如何排队在不同浏览器之间是不一样的)。

首先,在第一代码块里,有两个计时器触发:一个是10ms的setTimeout,一个是10ms的setInterval。在第一个代码块真正完成之前,它实际上已经释放了。但是,注意,它不会立即执行(由于单线程的问题,它无能为力),相反,为了能在下一个可行的时间得到执行,那些延时函数被编入队列。

另外,在第一个代码块内,我们看到鼠标点击出现。与这个异步事件(我们永远不知道何时执行动作,这样就可以认为它是不同步的)相关Javascript回调函数跟初始的计时器一样不能立即被执行,它排队等候执行。

在Javascript最初的代码块执行完毕之后,浏览器会发出疑问:正在等候执行的是什么?在这种情况下,鼠标点击处理器和计时器回调函数同时处于等待之中,然后,浏览器将选择一个并立即执行它,计时器函数将等到下一个可能的时间执行。

注意,当鼠标点击函数处理器执行时,第一个回调函数也在执行,至于计时器,其处理器被编入队列稍后执行。但是,请注意,当Interval再次释放时(在计时器处理器执行时),计时器执行的时间将减少。如果你在一大块代码执行期间将所有的Interval回调函数编入队列,其结果是一大群Interval回调函数会毫无延迟的执行,直到全部完成。而浏览器在队列增大之前只是简单的等到没有Interval处理器排队为止(间歇问题)。

事实上,我们看到这样一个情况:Interval正在执行时,第三个Interval函数将释放。这表明一个重要的事实:Interval对当前正在执行什么漠不关心,它们将不会青红皂白的排队,即使是牺牲回调函数之间的时间也在所不辞。

最后,在第二个Interval函数执行完毕之后,我们可以看到没有留下任何Javascript引擎执行的东西。也就是说,浏览器在等待一个新的异步事件的出现。Interval再次释放时,我们在50ms处获得它,但这一次,执行起来没有任何障碍,它立即释放。

我们来看一个例子,以便更好的说明setTimeout和setInterval的差异:

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. 如果有充分的执行时间,Interval可能会毫无延迟的来回执行。

所有这些无疑是重要的知识,了解Javascript引擎如何工作,特别是有大量异步事件出现时,这使得在构建高级应用代码片段时有一个良好的基础。

(责任编辑:IT教学网)

更多

推荐Javascript/Ajax文章