首页 > 解决方案 > 为什么 setTimeout(.., 0) 在 Firefox 中的浏览器操作之前触发?漏洞?

问题描述

我有一个input.onkeydown处理程序,我input.valuesetTimeout(..0).

我希望在回调运行input.value时获得新值。setTimeout

在除 Firefox 之外的所有浏览器中都可以。在 Firefox 中并非总是如此。

要检查的代码是:

<input id="input">
<script>
  input.onkeydown = function() {
    setTimeout(() => this.value = this.value.toUpperCase());
  };
</script>

演示:http ://plnkr.co/edit/rZmiHdttSXNdpKkR8YbH?p=preview

当我在 之后将输入值大写时setTimeout(..0),它应该总是大写。但如前所述,在 Firefox 中并非如此。

这是演示视频;前几秒钟证明了问题:https ://jmp.sh/9XSROQ2

相关规范部分是https://dom.spec.whatwg.org/#concept-event-dispatch

我没有得到什么,还是这是 Firefox 中长期存在的错误?

PS如果我添加console.logsetTimeout我有时会看到旧值。

PPS 这个问题的目的是想知道我是否理解setTimeout正确。我熟悉各种大写的方法input;请不要建议oninput, requestAnimationFrame, 等。

标签: javascriptfirefox

解决方案


实际规格在这里,实际上并没有定义 keydown 和输入当前值变化之间的关系。

不管他们读什么,(强调我的)

对于没有定义输入激活行为但应用了这些事件的输入元素,任何时候用户在没有显式提交操作的情况下导致元素的值发生更改,用户代理必须排队一个任务以在输入元素上触发一个名为 input 的事件,气泡属性初始化为真。当控件失去焦点时,将触发相应的更改事件(如果有)。

因此,实际上指定input事件(无论如何您都应该听)必须异步触发。由于这个事件是证明当前值发生变化的事件,我不认为 Firefox 在下一个事件循环中应用由 Key 事件引起的变化的行为几乎不是错误;请记住,浏览器必须在事件结束后异步进行此更改(并且不能再被任何处理程序取消)。

一些附加说明(可能与真正的原因有关),输入组合字符(例如^+ a=> â)我在 macOS 上的 FF 中有 100% 的复制(因为是的,我怀疑它也可能与操作系统有关) .

但是,当然,即使它不违反任何规范,并且即使您有一个简单的修复(监听输入事件),您可能仍然希望至少提交一份错误报告,因为它的行为不像其他供应商那样。


推荐阅读