JavaScript事件队列和setTimeout(..)
JavaScript Event Queue and setTimeout(...)
代码发生了什么
var start = new Date();
setTimeout(function() {
var end = new Date();
console.log('Time elapsed with func1:',end - start, 'ms');
}, 500);
setTimeout(function() {
var end = new Date();
console.log('Time elapsed with func2:',end - start, 'ms');
}, 250);
while (new Date() - start < 1000) {}
日志:
Time elapsed with func2: 1001 ms
Time elapsed with func1: 1017 ms
我预计func1将首先被激发,因为它是第一个添加到事件队列中的事件。然后,由于JS的单线程特性,请等待func1返回,然后执行队列中的下一个事件func2
那么,发生了什么?
第一次关闭setTimeout()
是异步且无阻塞的。这意味着当你调用它时,它所做的只是注册新的计时器,然后立即返回。因此,当您的代码运行时,它将遵循以下步骤:
- 您注册
func1
定时器500ms - 您将
func2
计时器注册250毫秒 - 每个定时器都被添加到事件循环的定时器部分内的排序数据结构中,因此事件循环很容易知道并检查下一个要执行的定时器
- 开始
while
旋转循环。这个循环大约持续1000毫秒 - 当
while
旋转循环结束时,Javascript解释器可以返回事件循环,检查是否还有其他事情要做。它检查的一件事(事件循环的一个阶段)是查看是否有任何定时器可以运行。它检查计时器列表的头部,并看到它的时间已经过去了(这意味着它已经过了运行时间)。因此,它获取与func2计时器关联的回调并执行它。func2计时器位于列表的开头,因为它具有与之关联的最早时间 - 当该回调完成执行时,JS解释器再次将控制权返回到事件循环,在那里它再次检查是否没有其他事情要做。它会发现func1计时器现在位于列表的顶部,已经过了运行时间,因此它会获取与该计时器相关联的回调并执行它
因此,一旦while
旋转循环完成,就会得到func2
回调执行的输出,然后func1
回调执行。
请注意,这些计时器完全由事件驱动。没有中断当前正在执行的Javascript来执行计时器。出于这个原因,Javascript中的计时器是一种尽力而为的实现方式。如果从现在起将计时器设置为1000ms,那么与该计时器关联的回调将不早于1000ms运行,并且如果JS解释器在该计时器的指定时间正忙,则可能会晚于1000ms。
上面的描述中缺少定时器的一个方面(因为在您的情况下不会发生)是,如果没有while()
旋转循环,会发生什么。在这种情况下,您的代码在配置完两个计时器后立即将控制权返回到事件循环,事件循环会检查是否有计时器可以运行,但没有计时器可以运行。然后它会一直睡眠,直到有东西再次唤醒它,但睡眠时间不会超过下一个当前设置的计时器。
不,等等。它不会将您的超时调用添加到事件队列中。它由浏览器的webapi处理,然后当您的超时开始时,它会将您的函数添加到事件队列中。
这是什么:https://www.youtube.com/watch?v=8aGhZQkoFbQ#t=13m(从13:00开始)
Javascript是单线程的。即使有异步回调,它们也不是当前的。
这意味着,只有在整个代码完成执行后,才会调用(setTimeout(fn,num))中的代码。因此,如果num参数=5000。这意味着,函数setTimeout(…)将运行:在整个代码(即,不仅是到调用setTimeout时为止的代码,而且是所有代码)执行完毕+5秒之后。希望这能有所帮助。
- 有没有一种方法可以将我的JS函数排队到JSF事件队列中
- 如何删除 settimeOut 的队列工作
- jqm 忙时停止点击事件队列
- 我可以在 for 循环中设置多个 window.setTimeout 事件吗?
- Angular 和 PhoneGap 事件队列
- 是发送到事件队列的承诺回调
- JavaScript事件队列和setTimeout(..)
- javascript点击事件队列
- NodeJS理解事件队列
- 其中是node.js事件队列
- 事件队列函数回调
- 是否可以在JavaScript中访问事件队列?
- 按钮点击时的setTimeout事件不起作用
- PyV8:事件队列满
- JavaScript事件队列
- Internet Explorer 9拖拽事件阻塞事件队列
- 如何在事件队列中进行异步jsonp调用
- 理解node.js事件队列和process.nextTick
- 如何实现事件队列
- 当我们有多个settimeout时,javascript事件队列是如何工作的