美文网首页
JavaScript计时器的工作方式

JavaScript计时器的工作方式

作者: 魂斗驴 | 来源:发表于2021-05-03 14:21 被阅读0次

从根本上讲,了解JavaScript计时器的工作原理很重要。通常,由于它们位于单个线程中,因此它们的行为不直观。让我们首先检查一下我们可以访问的可构造和操纵计时器的三个函数。

  • var id = setTimeout(fn, delay);–启动单个计时器,该计时器将在延迟后调用指定的功能。该函数返回一个唯一的ID,以后可以使用该ID取消计时器。
  • var id = setInterval(fn, delay);–类似于setTimeout但连续调用该函数(每次都有延迟),直到被取消。
  • clearInterval(id);clearTimeout(id);–接受计时器ID(由上述任何一个函数返回),并停止计时器回调的发生。

为了了解计时器在内部的工作方式,有一个重要的概念需要探讨:不能保证计时器的延迟。由于浏览器中的所有JavaScript都在单线程上执行,因此异步事件(例如鼠标单击和计时器)仅在执行中存在空缺时才运行。最好用图表来演示,如下所示:

该图中有很多信息需要消化,但是完全理解它可以使您更好地了解异步JavaScript执行的工作方式。此图是一维的图:垂直方向我们有时间,以毫秒为单位。蓝色框代表正在执行的JavaScript的部分。例如,JavaScript的第一块执行大约18ms,鼠标单击块执行大约11ms,依此类推。

由于JavaScript一次只能执行一个代码(由于其单线程性质),因此这些代码块中的每一个都在“阻塞”其他异步事件的进程。这意味着,当发生异步事件(例如,单击鼠标,触发计时器或完成XMLHttpRequest)时,它会排队等待稍后执行(实际上该排队的发生方式肯定因浏览器而异,因此请考虑一下简化一下)。

首先,在JavaScript的第一块中,启动了两个计时器:10mssetTimeout和10ms setInterval。由于计时器的启动时间和地点,在我们实际完成第一段代码之前,它实际上会触发。但是请注意,它不会立即执行(由于线程原因,它无法执行该操作)。而是将延迟的功能排队,以便在下一个可用时刻执行。

另外,在第一个JavaScript块中,我们看到发生了鼠标单击。与该异步事件关联的JavaScript回调(我们不知道用户何时可以执行操作,因此它被认为是异步的)无法立即执行,因此,像初始计时器一样,它被排队等待稍后执行。

在JavaScript的初始块执行完之后,浏览器立即提出问题:正在等待执行什么?在这种情况下,鼠标单击处理程序和计时器回调都在等待。然后,浏览器选择一个(鼠标单击回调)并立即执行它。计时器将等到下一个可能的时间才能执行。

请注意,在执行鼠标单击处理程序时,将执行第一个间隔回调。与计时器一样,其处理程序也将排队等待稍后执行。但是,请注意,当再次触发间隔(当计时器处理程序正在执行时)时,该处理程序执行将被丢弃。如果要在执行一大段代码时将所有间隔回调排队,则结果将是一堆间隔执行,并且在完成后它们之间没有延迟。取而代之的是,浏览器倾向于简单地等待,直到没有更多的间隔处理程序排队(针对所讨论的间隔),然后再排队。

实际上,我们可以看到在间隔本身正在执行的同时触发了第三个间隔回调时就是这种情况。这向我们显示了一个重要的事实:间隔不关心当前正在执行什么,它们会不加选择地排队,即使这意味着将牺牲回调之间的时间。

最后,在第二个时间间隔回调完成执行之后,我们可以看到JavaScript引擎没有执行任何内容。这意味着浏览器现在等待新的异步事件发生。当间隔再次触发时,我们在50ms处获得此值。但是,这次没有任何东西阻止它的执行,因此它立即触发。

让我们看一个例子,以更好地说明之间的差异setTimeoutsetInterval

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

乍一看,这两段代码在功能上似乎是等效的,但事实并非如此。值得注意的是,setTimeout代码在上一次执行回调之后将始终至少有10ms的延迟(最终可能会更多,但永远不会更少),而setInterval无论最后一次执行回调的时间如何,都会尝试每10ms执行一次回调。

我们在这里学到了很多东西,让我们回顾一下:

  • JavaScript引擎只有一个线程,从而迫使异步事件排队等待执行。
  • setTimeout并且setInterval它们执行异步代码的方式根本不同。
  • 如果定时器被阻止立即执行,它将被延迟到下一个可能的执行点(比所需的延迟时间更长)。
  • 如果间隔执行的时间足够长(比指定的延迟时间长),则间隔可以无延迟地背对背执行。

所有这些都是非常重要的基础知识。了解JavaScript引擎的工作原理,尤其是通常发生的大量异步事件,为构建高级应用程序代码奠定了良好的基础。

参考

How JavaScript Timers Work

相关文章

网友评论

      本文标题:JavaScript计时器的工作方式

      本文链接:https://www.haomeiwen.com/subject/dovolltx.html