如果由于脚本中的某个长时间运行的方法而将一堆 UIEvents 排队,并且在方法 I 结束时,相对于先前排队的事件的处理程序,setTimeout(myfunc, 0)
将调用什么顺序?myfunc
是否保证在处理所有先前排队的事件后调用它?
2 回答
浏览器中的大多数事件通过中央事件队列以 FIFO 顺序(先进先出)处理。某些 UI 事件(例如 mousemove 事件)是折叠的,因此您可以获得最新状态,而不一定是所有中间事件。
所以,问题实际上是鼠标事件何时进入 JS 事件队列。我不太确定这是如何工作的,所以我构建了几个测试演示。我发现答案取决于。如果 UI 事件占用了 JS 线程,那么看起来其他 UI 事件没有进入计时器前面的队列,但是如果 UI 事件完成并且其他一些操作(不在 UI 上)占用CPU,然后 evnet 以正确的 FIFO 顺序排队。因此,似乎“它取决于”(在 Chrome 中,这是我迄今为止测试过的)。
我将在一秒钟内发布演示链接...
此演示显示,如果 CPU 占用活动不是响应按钮单击,则在setTimeout()
计划触发之前发生的其他按钮单击将在以下事件之前得到处理setTimeout()
:
long
click
click
click
timeout
但是,这个在按钮单击事件处理程序本身中发生 CPU 占用的演示显示了相反的情况。在预定触发之前发生的点击setTimeout()
没有在它之前得到处理。
long
timeout
click
click
click
现在,我在 Firefox 中运行了它们,发现在这两种情况下,Firefox 都以 FIFO 顺序处理事件(按照它们实际发生的顺序)。对于上面的第二个演示,这与 Chrome 不同。
现在,我在 IE 中运行了这些,发现 IE 总是处理setTimeout()
UI 事件之前的事件 - 与 Firefox 和 Chrome 不同。
因此,这些测试在三种不同的浏览器中显示了三种不同的结果。
总结结果:
Browser Hog CPU in Event Handler Hog CPU after Event Handler
---------------------------------------------------------------------
Chrome 44 timeout first (not FIFO) FIFO clicks first
Firefox 39 FIFO clicks first FIFO clicks first
IE 11 timeout first (not FIFO) timeout first (not FIFO)
作为参考,这是在按钮单击事件处理程序中占用 CPU 的测试用例:
document.getElementById("test").addEventListener("click", function() {
log("click");
});
document.getElementById("long").addEventListener("click", function() {
log("long");
setTimeout(function() {
log("timeout");
}, 1900)
// hhog the CPU here before the event handler finishes
var t = Date.now();
while (Date.now() - t < 2000) {}
});
而且,这是在按钮客户端事件处理程序完成后占用 CPU 的测试用例。
document.getElementById("test").addEventListener("click", function() {
log("click");
});
document.getElementById("long").addEventListener("click", function() {
log("long");
// schedule a setTimeout
setTimeout(function() {
log("timeout");
}, 1900)
// hog the CPU, but after the UI event has finished
setTimeout(function() {
// spin for 2 seconds to hog the JS thread
var t = Date.now();
while (Date.now() - t < 2000) {}
}, 1);
});
在做了一些测试之后,我必须编辑我的答案,因为我不正确。是的,UI 事件确实优先于超时。对于超时,似乎无论设置什么顺序,UI 事件都会首先发生。