JS 处理事件与侦听器并行发生 运行
JS processing events happening parallel to listeners running
我不确定,一些JS代码是如何生成事件的运行。
例如在这种情况下:
<div id="div1"> text </div>
<div id="div2"> text </div>
div2.onpointermove = (e) => {
console.log("old handler");
};
div1.onpointerdown = (e) => {
div2.onpointermove = (e) => {
console.log("new handler");
}; };
布局:
+-----+-----+
|div1 | div2|
+-----+-----+
场景:
- pointerdown 在
div1
的边缘像素上
- 指针移出
div1
并进入 div2
当 JS 代码在单线程上运行时,用户可以将鼠标平行移动到某些 JS 代码 运行。我想知道,事件是如何生成然后处理的,而一些JS代码是运行?
可能的时间表:
A)
- 指针指向
div1
的边缘像素
- 将鼠标移到
div2
平行事件监听JS代码运行
- 当 JS 代码处理事件侦听器时,鼠标事件 排队
- 调用
div1.onpointerdown
- 添加新处理程序
div2.onpointermove
- 使用新 组侦听器
处理排队的鼠标事件
- “新处理程序”打印在控制台上
B)
- 指针指向
div1
的边缘像素
- 将鼠标移到
div2
平行事件监听JS代码运行
- 当JS代码处理事件监听器时,鼠标事件被忽略
- 调用
div1.onpointerdown
- 添加新处理程序
div2.onpointermove
- 再次开始注册活动
div2
上的指针移动丢失,控制台上没有打印任何内容(如果鼠标在 div1.onpointerdown
完成处理后没有移动,并且 JS 之前没有比较鼠标位置-处理代码块后)
C)
- 指针向下指向
div1
的边缘像素
- 将鼠标移到
div2
平行事件监听JS代码运行
- 当 JS 代码处理事件侦听器时,鼠标事件 排队 与当前的 old 事件集一起处理听众
- 调用
div1.onpointerdown
- 添加新处理程序
div2.onpointermove
- 使用旧、记录的事件侦听器
处理队列中的下一个事件
- “旧处理程序”打印在控制台上
我不知道,会发生哪种情况,或者是否取决于浏览器?
pointerdown
、pointermove
仅用于示例目的,我对这些确切事件的怪癖不感兴趣,而是对事件如何发生的更一般概念感兴趣 generated/saved/ignored/handled 而一些 JS 代码是 运行,它为那些与代码块并行发生的事件添加事件处理程序 运行.
此外,是否存在通用行为,或者是否存在特定于实现的细节?
通常,使用方法 A - 事件排队,然后在 JS 事件循环完成先前处理程序的执行后处理。
但是,快速且连续(不离散)的事件,如滚动或鼠标移动(与点击或按键相反)可以被引擎限制,因此如果处理它们的 JS 代码花费很长时间。这可能相当于丢弃一些事件(方法 B)——但你怎么知道?
至于方法C,没用过。排队的是事件,而不是 运行 已注册处理程序的任务。这在删除事件侦听器时尤为重要 - 在您调用 removeEventListener
后,您可以确定它不会被再次调用,即使事件仍在排队中可能会触发它。但是,对于安装新的事件侦听器,并没有真正区分差异的方法 - 代码无法判断事件是在安装侦听器之前还是之后触发的,因此这为浏览器提供了一些优化余地。
我不确定,一些JS代码是如何生成事件的运行。
例如在这种情况下:
<div id="div1"> text </div>
<div id="div2"> text </div>
div2.onpointermove = (e) => {
console.log("old handler");
};
div1.onpointerdown = (e) => {
div2.onpointermove = (e) => {
console.log("new handler");
}; };
布局:
+-----+-----+
|div1 | div2|
+-----+-----+
场景:
- pointerdown 在
div1
的边缘像素上
- 指针移出
div1
并进入div2
当 JS 代码在单线程上运行时,用户可以将鼠标平行移动到某些 JS 代码 运行。我想知道,事件是如何生成然后处理的,而一些JS代码是运行?
可能的时间表:
A)
- 指针指向
div1
的边缘像素
- 将鼠标移到
div2
平行事件监听JS代码运行 - 当 JS 代码处理事件侦听器时,鼠标事件 排队
- 调用
div1.onpointerdown
- 添加新处理程序
div2.onpointermove
- 使用新 组侦听器 处理排队的鼠标事件
- “新处理程序”打印在控制台上
B)
- 指针指向
div1
的边缘像素
- 将鼠标移到
div2
平行事件监听JS代码运行 - 当JS代码处理事件监听器时,鼠标事件被忽略
- 调用
div1.onpointerdown
- 添加新处理程序
div2.onpointermove
- 再次开始注册活动
div2
上的指针移动丢失,控制台上没有打印任何内容(如果鼠标在div1.onpointerdown
完成处理后没有移动,并且 JS 之前没有比较鼠标位置-处理代码块后)
C)
- 指针向下指向
div1
的边缘像素
- 将鼠标移到
div2
平行事件监听JS代码运行 - 当 JS 代码处理事件侦听器时,鼠标事件 排队 与当前的 old 事件集一起处理听众
- 调用
div1.onpointerdown
- 添加新处理程序
div2.onpointermove
- 使用旧、记录的事件侦听器 处理队列中的下一个事件
- “旧处理程序”打印在控制台上
我不知道,会发生哪种情况,或者是否取决于浏览器?
pointerdown
、pointermove
仅用于示例目的,我对这些确切事件的怪癖不感兴趣,而是对事件如何发生的更一般概念感兴趣 generated/saved/ignored/handled 而一些 JS 代码是 运行,它为那些与代码块并行发生的事件添加事件处理程序 运行.
此外,是否存在通用行为,或者是否存在特定于实现的细节?
通常,使用方法 A - 事件排队,然后在 JS 事件循环完成先前处理程序的执行后处理。
但是,快速且连续(不离散)的事件,如滚动或鼠标移动(与点击或按键相反)可以被引擎限制,因此如果处理它们的 JS 代码花费很长时间。这可能相当于丢弃一些事件(方法 B)——但你怎么知道?
至于方法C,没用过。排队的是事件,而不是 运行 已注册处理程序的任务。这在删除事件侦听器时尤为重要 - 在您调用 removeEventListener
后,您可以确定它不会被再次调用,即使事件仍在排队中可能会触发它。但是,对于安装新的事件侦听器,并没有真正区分差异的方法 - 代码无法判断事件是在安装侦听器之前还是之后触发的,因此这为浏览器提供了一些优化余地。