0

如果由于脚本中的某个长时间运行的方法而将一堆 UIEvents 排队,并且在方法 I 结束时,相对于先前排队的事件的处理程序,setTimeout(myfunc, 0)将调用什么顺序?myfunc是否保证在处理所有先前排队的事件后调用它?

4

2 回答 2

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);
});
于 2015-08-21T21:05:39.033 回答
0

在做了一些测试之后,我必须编辑我的答案,因为我不正确。是的,UI 事件确实优先于超时。对于超时,似乎无论设置什么顺序,UI 事件都会首先发生。

于 2015-08-21T21:05:47.050 回答