手机版

JavaScrip单线程引擎工作原理分析

时间:2021-11-23 来源:互联网 编辑:宝哥软件园 浏览:

在基础层面,理解JavaScript的计时器是如何工作的非常重要。计时器的执行往往与我们的直观想象不同,因为JavaScript引擎是单线程的。让我们首先了解以下三个函数是如何控制计时器的。我们推荐阅读:JavaScript初学者的10个小技巧抄码如下: var id=setTimeout(fn,delay);初始化计时器,然后在指定的时间间隔后执行它。这个函数返回一个唯一的标志标识(数字类型),我们可以用它来取消定时器。复制代码如下:VAR ID=setinterval (fn,delay);它有点类似于setTimeout,但它会连续调用一个函数(时间间隔是延迟参数),直到它被取消。复制代码如下: clearInterval(id);cleartime out(id);使用定时器id(settimeout和setInterval的返回值)取消定时器回调的发生。为了理解定时器的内部执行原理,有一个重要的概念需要讨论:定时器的延迟无法保证。由于所有的JavaScript代码都在一个线程中执行,所有的异步事件(比如鼠标点击和定时器)只有在有机会执行的情况下才会被执行。用好的图表解释一下:

这张图表中有很多信息需要理解。如果你完全理解它们,你就会很好地理解JavaScript引擎是如何实现异步事件的。这是一维图标:垂直方向代表时间,蓝色块代表JavaScript代码执行块。比如第一个JavaScript代码执行块需要18ms左右,鼠标点击触发的代码执行块需要11ms等。因为JavaScript引擎一次只执行一个代码(这是因为JavaScript的单线程特性),所以每个JavaScript代码执行块都会“阻塞”其他异步事件的执行。这意味着当一个异步事件发生时(比如鼠标点击、定时器触发、或者Ajax异步请求),这些事件的回调函数会在执行队列的末尾排队,等待执行(其实排队的方式因浏览器不同而异,所以这只是一种简化);在第一个JavaScript执行块中,初始化了两个计时器:10ms的setTimeout()和10ms的setInterval()。根据定时器初始化的时间和地点(定时器将在初始化后开始计数),定时器实际上将在第一个代码块执行之前被触发。但是,绑定到计时器的函数不会立即执行(原因是JavaScript是单线程的)。事实上,延迟的函数将依次排在执行队列的末尾,等待下一个合适的时间执行。此外,在第一个JavaScript执行块中,我们看到了一个“鼠标点击”事件。一个JavaScript回调函数绑定到这个异步事件(我们永远不知道用户什么时候会执行这个(click)事件,所以我们认为是异步的),这个函数不会立即执行。和上面的计时器一样,它会在执行队列的末尾,等待下一个合适的时间执行。当第一个JavaScript执行块完成后,浏览器会立即问一个问题:哪个函数(语句)在等待执行?此时,一个“鼠标点击事件处理程序”和一个“定时器回调函数”正在等待执行。浏览器会选择一个(其实是选择了“鼠标点击事件处理程序”,因为从图中可以看出是高级团队)立即执行。而定时器回调函数将等待下一个合适的时间执行。请注意,setInterval的回调函数是在执行“鼠标点击事件处理程序”时首次触发的。像setTimeout的回调函数一样,它将排队到执行队列的末尾等待执行。但是,必须注意的是,当第二次触发setInterval回调函数时(当setTimeout函数仍在执行时),setTimeout的第一个触发器将被丢弃。当执行一个长代码块时,所有的setInterval回调函数都可以放在执行队列的后面。代码块执行后,结果将是一长串等待执行的setInterval回调函数,这些函数之间没有间隔,直到它们全部完成。因此,浏览器倾向于在没有间隔的更多处理函数时,将下一个处理函数排队在队列的末尾(这是由于间隔问题)。我们可以发现,当第三个setInterval回调函数被触发时,前面的setInterval回调函数仍然在执行。这显示了一个非常重要的事实:setInterval不考虑当前正在执行什么,而是将所有阻塞的函数排列在队列的末尾。这意味着两个setInterval回调函数之间的时间间隔将被牺牲(缩短)。最后,当执行第二个setInterval回调函数时,我们可以看到没有等待JavaScript引擎执行的程序。这意味着浏览器现在正在等待一个新的异步事件发生。在50毫秒时,新的setInterval回调函数再次被触发。此时,没有执行块阻止其执行。所以会立即执行。

让我们用一个例子来说明setTimeout和setInterval之间的区别:复制代码如下: SetTimeout (function () {/*一些长代码块.*/SetTimeout(参数。被呼叫者,10);}, 10);setInterval(函数(){ /*一些长代码块.*/}, 10);setTimeout(函数(){ /*一些长代码块.*/setTimeout(arguments.callee,10);}, 10);setInterval(函数(){ /*一些长代码块.*/}, 10);乍一看,这两个代码没有区别,但它们是不同的。setTimeout回调函数的执行与最后一次执行之间的时间间隔至少为10ms(可能更长,但不小于10ms),而setInterval的回调函数将尝试每10ms执行一次,无论最后一次执行是否完成。总结JavaScript引擎单线程,强制所有异步事件排队执行;执行异步代码时,setTimeout和setInterval有着本质的区别;如果定时器被阻塞,不能立即执行,将被延迟到下一个可能的执行时间(比预期的时间间隔长);如果setInterval回调函数的执行时间足够长(长于指定的时间间隔),它们将连续执行,并且它们之间没有时间间隔。这些知识点非常重要。了解JavaScript引擎如何工作,尤其是当大量异步事件(连续)发生时,可以为构建高级应用程序打下良好的基础。原创作者:约翰瑞西原创链接:http://ejohn.org/blog/how-javascript-timers-work/.

版权声明:JavaScrip单线程引擎工作原理分析是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。