对于以下测试用例(我用 setTimeout 替换了 XHR 调用,以表示具有非常快响应的 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左右)的订单是
- 焦点
- 鼠标按下
- 模糊
- 计时器
- 鼠标松开
- 点击
“blur”和“timer”事件用于输入字段及其 setTimeout()
回调。如果我将超时间隔设置得更长,例如 150 毫秒左右,那么我会得到
- 焦点
- 鼠标按下
- 模糊
- 鼠标松开
- 点击
- 计时器
我认为,这是有道理的:“mousedown”和“mouseup”事件是由您与鼠标按钮的实际物理交互驱动的。在收到“mouseup”之前,“click”事件没有意义。通过“模糊”处理程序中的短计时器,计时器可以在鼠标通过操作系统等物理传达“向上”事件之前触发。
关于JavaScript 事件队列 : XHR response in blur queued before parent onclick,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53088239/