首页 > 解决方案 > JavaScript 事件循环:不同类型事件的不同队列?

问题描述

摘自“Javascript Ninja 的秘密”一书:

事件是异步的

事件发生时,可能会在不可预知的时间以不可预知的顺序发生(强制用户按特定顺序按键或单击是很棘手的)。我们说事件的处理以及它们处理函数的调用是异步的。

除其他外,可能会发生以下类型的事件:

■ 浏览器事件,例如页面何时完成加载或何时卸载

■ 网络事件,例如来自服务器的响应(Ajax 事件、服务器端事件)

■ 用户事件,例如鼠标点击、鼠标移动和按键

■ 定时器事件,例如超时到期或间隔触发时

以上所有这些事件是否由事件循环中的同一个队列处理?我在尝试测试脚本中的 DOM 点击事件时遇到了这个疑问:

<html>

<body>
    <button id="bId">A button</button>

</body>
<script>
    function testing() {
        document.getElementById('bId').addEventListener("click", function () {
            console.log('clicked');
        })
        console.log('before click');
        document.getElementById('bId').click();
        console.log('after click')
    };
    testing();
</script>

</html>

据我了解,任何使用事件循环队列的异步事件(如计时器、承诺)都将等待调用堆栈为空。

在上面的代码中,如果 DOM 事件正在使用事件循环队列,不应该在and函数调用clicked之后打印输出吗?before clickafter click console.log()

不同类型的事件是否有不同类型的队列?

标签: javascripthtmldom

解决方案


我认为这可能会有所帮助,但它也会按直接调用的点击顺序打印,看起来它们是相同的。

这就是 mdn 不得不说的:

在指定的 EventTarget 处分派一个事件,(同步地)以适当的顺序调用受影响的 EventListener。正常的事件处理规则(包括捕获和可选的冒泡阶段)也适用于使用 dispatchEvent() 手动调度的事件。

但我很确定当元素被用户物理点击时,情况并非如此。

<html>

<body>
    <button id="bId">A button</button>

</body>
<script>
    function testing() {
        document.getElementById('bId').addEventListener("click", function () {
            console.log('clicked');
        })
        console.log('before click');

        var el = document.getElementById('bId');
        var event;
        if (window.CustomEvent) {
           event = new CustomEvent('click');
        } else {
           event = document.createEvent('click');
           event.initCustomEvent('click', true, true);
        }
        el.dispatchEvent(event);
        console.log('after click')
    };
    testing();
</script>

</html>


推荐阅读