javascript /浏览器:什么时候事件调度完全发生? [英] javascript/browser: when does event dispatching exactly happen?

查看:163
本文介绍了javascript /浏览器:什么时候事件调度完全发生?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SO问题&答案 DOM level3文档指出,手册事件在浏览器中同步调度 。但是,我的问题涉及用户相关事件(实际点击),而不是手动触发。

This SO question & answers and DOM level3 docs states that manual events are dispatched synchronously in browsers. My question, however, relates to user-related events (real clicks), not manually triggered ones.

我创建了一个小jsfiddle演示与按钮+ onclick处理程序,处理程序做一些同步工作2秒(阻止同步等待,足够长的时间,我的眼睛看到发生了什么)。打开控制台以查看 console.log s。

I created a small jsfiddle demo with a button + onclick handler, the handler does some synchronous work for 2 seconds (blocking sync wait, long enough for my eye to see what's going on). Open console to see console.logs.

测试。我点击几下按钮。虽然第一次点击(及其同步处理)使按钮按下(看起来像禁用),但其他点击也被存储,并通过事件循环异步处理。

The test. I click several times on the button. Although the first click (and its synchronous processing) makes the button pushed down (looks like disabled), other clicks are stored as well and processed later, asynchronously, via event loop.

问题是:


  • 事件调度何时完全发生?用户事件(例如,点击)是否立即被推送到JS消息队列,或者是否有一个中间Web API队列?或者换句话说 - 这个事件调度与哪个队列相关?

  • 大多数事件(点击 blur 等 - 除了 load )在用户事件(不是手动)的情况下同步处理?考虑到上面的测试,第一次点击使得同步阻塞回调执行(我期望在此期间别无其他事情),无论如何,下一次点击被存储在队列中。所以存储事件是平行的(必须是,因为主javascirpt线程忙)。会有什么不同,理论上事件是异步处理的?

  • when does event dispatching exactly happen? Are user events (e.g. a click) immediately pushed to JS message queue or is there an intermediate Web API queue... or in other words - which queue is this event dispatching related to?
  • what does it mean that most events (click, blur, etc - except for load) are processed synchronously in case of user events (not manual ones)? Given the test above, 1st click makes synchronous blocking callback executed (I expect nothing else to happen in the meantime) and, anyway, next clicks are stored in a queue. So storing events is parallel anyway (has to be, since main javascirpt thread is busy). Would there be any difference, theoretically, it events were processed asynchronously?

略有修改的演示显示,对于给定的点击事件,事件会起起来,并调用所有相关的事件处理程序,如如果事件冒泡被阻止,直到其他任何事情(在本例中为超时)可能发生。但是仍然不清楚为什么事件调度同步。

slightly modified demo shows that for a given click event, the event bubbles up and calls all related event handlers, like if event bubbling was blocking, until anything else (timeout in this example) can happen. But still it's not clear why is event dispatching synchronous.

推荐答案

说说因为事件队列只在当前执行堆栈被清空时被处理,即当没有更多的同步代码被执行时,才会在实际的事件的上下文中同步。这使得相关的事件处理程序异步。对于您在小提琴中提供的点击事件处理程序也是如此。

It makes little sense to speak of synchronous in the context of real events, since the event queue is only processed when the current execution stack has been emptied, i.e. when there is no more synchronous code to execute. That makes the related event handlers asynchronous. This is also true for the click event handler you provided in a fiddle.

正在运行的代码在运行时阻止任何其他操作,并不表示该代码被触发:异步或同步在这两种情况下,2秒钟的忙环路将被阻塞2秒。当我们说代码异步运行时,它只会说明如何/何时调用代码,而不是运行代码。同步和异步代码都以阻止它们的方式运行。这有一些例外 - 例如网络工作者在自己的线程中运行。

That the running code blocks any other action while it runs is no indication of how that code was triggered: asynchronously or synchronously. In both cases a busy loop for 2 seconds will be blocking for 2 seconds. When we say code runs asynchronously, it only says something of how/when the code was invoked, not on how it runs. Both synchronous and asynchronous code run in a way that they are blocking. There are some exceptions to this -- for instance web workers run in their own thread.

这些真实事件被推送到JS消息队列中。当然,它们首先从OS事件队列中消耗,但是这个实现是特定的。重要的是他们最终会在JS消息队列中加上一个处理程序。 JavaScript引擎仅在以前运行的代码运行时才处理事件完成。因此这些事件处理程序被异步地调用。

These "real" events are pushed on the JS message queue. Of course, they first are consumed from an OS event queue, but this implementation specific. The important thing is that they end up in the JS message queue, together with a handler for them. The JavaScript engine only processes events when the previously running code ran to completion. By consequence these event handlers are called asynchronously.

在手动事件的情况下,即由jQuery的 .trigger() 方法,在异步和同步之间有区别的意义。在异步情况下,事件将放在JS队列上,当前的代码将首先运行到完成。在同步情况下,事件不会放在JS队列上,而是像函数调用那样执行。因此,事件的处理发生在调用堆栈上的额外调用,之后您的代码将恢复,就像从正常的函数调用返回后一样:这是同步行为。

In case of "manual" events, i.e. events triggered by code such as jQuery's .trigger() method, there is a sense in making the difference between asynchronous and synchronous. In the asynchronous case, the event would be put on the JS queue, and the current code would first run to completion. In the synchronous case, the event would not be put on the JS queue, but be executed like a function call. So the handling of the event happens as an additional call on the call stack, after which your code will resume, just like after the return from a normal function call: this is synchronous behaviour.

我在此忽略了微任务的概念,这仅仅意味着执行异步代码有不同的优先级。

I ignore here the concept of micro tasks, which just means there are different priorities for executing asynchronous code.

这篇关于javascript /浏览器:什么时候事件调度完全发生?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆