JavaScript定时器的工作原理(翻译)

简介: JavaScript定时器的工作原理(翻译)标签(空格分隔): JavaScript定时器最近在看ajax原理的时候,看到了一篇国外的文章,讲解了JavaScript定时器的工作原理,帮助我很好的理解了js的单线程工作模式。

JavaScript定时器的工作原理(翻译)

标签(空格分隔): JavaScript定时器


最近在看ajax原理的时候,看到了一篇国外的文章,讲解了JavaScript定时器的工作原理,帮助我很好的理解了js的单线程工作模式。在这里翻译一下供大家参考,原文地址.
翻译正文
从根本上讲,了解JavaScript定时器的工作原理非常重要。通常 js的单线程表现的。让我们首先看一下可以构造和操作定时器的三个函数。


 - 启动单个定时器,在延迟后调用指定的功能。该函数返回一个唯一的ID,该Id可以用于取消定时器
    var id = setTimeout(fn, delay); 
 - 类似setTimeout但不断地调用函数(每次都有延迟),直到它被取消,类似于定时任务。同上也返回唯一ID用于取消定时器
    var id = setInterval(fn, delay); 
 - 接受计时器ID(由上述任一功能返回)并停止触发计时器回调。
    clearInterval(id);
    clearTimeout(id); 

为了理解定时器的内部工作原理,我们需要探索一个重要的概念:定时器延迟并不能保证准确。由于浏览器中的所有JavaScript都在单个线程上执行,因此异步事件(例如鼠标单击和计时器)仅在可被执行时运行。使用图表可以最好地证明这一点,如下所示:

这里写图片描述

这个图中有很多信息需要理解,完全理解它会让你更好地了解异步JavaScript执行的工作方式。这个图是一维的:垂直方向,我们有(挂钟)时间(译注:左侧的时间刻度),以毫秒为单位。蓝色框表示正在执行的JavaScript部分。例如,第一个JavaScript块执行大约18ms,鼠标单击块大约需要11ms,依此类推。

由于JavaScript一次只能执行一段代码(由其单线程性质决定),因此每个代码块都“阻塞”其他异步事件的进度。这意味着当异步事件发生时(如鼠标单击,计时器触发或XMLHttpRequest完成),它会先排队等待(译注:可以理解为一个队列)以后执行(这种排队实际发生的方式因浏览器到浏览器而异,这里是做了一个简单说明)。

首先,在JavaScript的第一个块中,启动两个定时器:10ms setTimeout和10ms setInterval。由于计时器启动的位置和时间,它实际上在我们实际完成第一个代码块之前触发。但请注意,它不会立即执行(由于线程,它无法执行此操作)而是进入排队队列,以便在下一个可用时刻执行。

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

在JavaScript的初始块完成后,执行浏览器会立即询问:队列中有什么等待执行的任务?在这种情况下,鼠标单击处理程序和计时器回调都在等待。然后浏览器选择一个(鼠标单击回调)并立即执行它。计时器将等到下一个时间被从队列中取出执行。

请注意,当鼠标单击处理程序执行时,执行第一个间隔回调。与计时器一样,它的处理程序进入排队等待以后执行。但是,请注意,当再次触发间隔时(在执行timer程序时),此时Interval的间隔回调被丢弃(译者注:这里不是很理解,欢迎留言交流指教。是否是因为已经有interval在排队?)。如果要在执行大块代码时调用间隔回调,间隔回调将连续加入到任务队列中,它们之间没有延迟。浏览器往往只是简单的去队列中取任务直到队列中没有其他任务。

事实上,我们可以看到,当间隔本身正在执行时,第三个间隔回调会触发。这向我们展示了一个重要的事实:Intervals不关心当前正在执行的内容,它们会不加选择地排队。

最后,在第二个间隔回调完成执行后,我们可以看到JavaScript引擎没有任何任务可以执行。这意味着浏览器现在等待发生新的异步事件。当间隔再次触发时,在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的延迟(它可能最终会更多,但绝不会少于10ms),而setInterval在这段长代码执行期间它都会尝试每10ms执行一次回调(译者注:可理解为在这段长代码执行期间,会每10ms添加一个任务进队列,中间无间隔)。

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

JavaScript引擎只有一个线程,迫使异步事件排队等待执行。
setTimeout并且setInterval它们在执行异步代码方面有着根本的不同。
如果计时器被阻止立即执行,它将被延迟到下一个可能的执行点(这将超过所需的延迟)。
如果setInterval中回调程序执行时间足够长(超过指定的延迟),则间隔可以无延迟地执行(译者注:因为在一个回调没有运行完的时候就会再加入一个回调)。
所有这些都是用来了解JavaScript引擎的工作原理的非常重要的知识,尤其是发生的大量异步事件的时候,为构建高级应用程序代码奠定了基础。

希望大家多评论交流,互相学习
目录
相关文章
|
8月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
335 19
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理与实战
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理与实战
|
11月前
|
JavaScript 前端开发 Java
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
Array.find() 是 JavaScript 数组方法中一个非常实用和强大的工具。它不仅提供了简洁的查找操作,还具有性能上的独特优势:返回的引用能够直接影响原数组的数据内容,使得数据更新更加高效。通过各种场景的展示,我们可以看到 Array.find() 在更新、条件查找和嵌套结构查找等场景中的广泛应用。 在实际开发中,掌握 Array.find() 的特性和使用技巧,可以让代码更加简洁高效,特别是在需要直接修改原数据内容的情形。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
11月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
11月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
398 17
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
562 1
|
前端开发 JavaScript
深入理解JavaScript中的事件循环(Event Loop):从原理到实践
【10月更文挑战第12天】 深入理解JavaScript中的事件循环(Event Loop):从原理到实践
517 1
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理、应用与代码演示
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理、应用与代码演示

热门文章

最新文章