javascript - Javascript事件队列:XHR响应在父onclick之前排队
问题描述
对于以下测试用例(我将 XHR 调用替换为 setTimeout 以表示响应非常快的 XHR 调用):
<html>
<body>
<div onclick="console.log('onclick parent')">
Event Queue Test:
<input type=text onblur="console.log('onblur'); setTimeout(function() {console.log('onblur timeout')})"/>
</div>
</body>
</html>
如果我单击文本字段,然后单击文本字段前面的文本,我会在 Chrome (v70) 中获得以下输出:
onblur
onblur timeout
onclick parent
我本来希望父 onclick 处理程序在 setTimeout 事件之前排队。至少在 Chrome 中,它没有。这种行为是由标准指定的还是依赖于实现的?我也对始终让父 onclick 处理程序在超时(或 XHR)处理程序之前运行的变通方法感兴趣。
在我的实际用例中,这个问题是有问题的,因为不能保证事件以相同的顺序排队,这取决于 XHR 请求运行多长时间。
解决方案
这不一定会帮助您解决实际的 XHR 问题,但我想我了解发生了什么。为了方便起见,我使用 jQuery 扩展了您的示例代码:
<div class=parent>Label: <input class=field></div>
和 JavaScript:
var $d = $(document);
var t = {
mousedown: -1,
mouseup: -1,
focus: -1,
click: -1,
blur: -1,
timer: -1
};
["mousedown", "mouseup", "focus", "click"].forEach(function(event) {
$d.on(event, ".parent", function() {
t[event] = Date.now();
})
});
$d.on("blur", ".field", function() {
t.blur = Date.now();
setTimeout(function() {
t.timer = Date.now();
}, 150);
});
$d.on("click", ".parent", function() {
setTimeout(function() {
var race = Object.keys(t).sort(function(k1, k2) { return t[k1] - t[k2];});
console.log("Result: ", race);
race.forEach(function(key) { t[key] = -1; });
}, 1000);
});
该代码所做的是按事件实际发生的时间对事件进行排序。在输入框点击聚焦后点击文本的情况下,超时时间短(小于100ms左右)的顺序为
- 重点
- 鼠标按下
- 模糊
- 计时器
- mouseup
- 点击
“模糊”和“计时器”事件用于输入字段及其setTimeout()
回调。如果我让超时间隔更长,比如 150 毫秒左右,那么我会得到
- 重点
- 鼠标按下
- 模糊
- mouseup
- 点击
- 计时器
我认为这是有道理的:“mousedown”和“mouseup”事件是由您与鼠标按钮的实际物理交互驱动的。在收到“mouseup”之前,“click”事件没有意义。使用“模糊”处理程序中的短计时器,计时器可以在鼠标通过您的操作系统等物理传达“向上”事件之前触发。
推荐阅读
- r - 在 dplyr group_by 和计数中找不到对象错误
- java - 无法覆盖 onBeforeConvert:“......具有相同的擦除,但都不会覆盖另一个”
- node.js - 使用节点验证器、节点邮件程序和 ejs 验证复选框
- python - 如何在firebase集合中为文档标题设置实时监听器 - python
- quickbooks - Consolibyte QuickBooks PHP 库 - 导入所有活跃客户
- asp.net-core - 没有指定 authenticationScheme,也没有找到 DefaultChallengeScheme
- python - 如何让子键迭代并最终在 AWS S3 中迭代其中的文件
- javascript - 如何在 React 重新渲染之前过渡动画?
- java - JUnit 如何在 Optional 和对象上断言 True/Equals
- angular - 如何在表单数组中添加无效的表单控件而不影响其功能