为什么setTimeout(..,0)在Firefox中的浏览器动作之前触发?虫子?

时间:2019-06-25 08:45:05

标签: javascript firefox

我有一个input.onkeydown处理程序,并且在input.value之后检查了setTimeout(..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中的一个长期存在的错误?

P.S。如果我在console.log中添加setTimeout,有时会看到旧值。

P.P.S。这个问题的目的是知道我是否正确理解setTimeout。我熟悉各种大写input的方式;请不要建议oninputrequestAnimationFrame等。

2 个答案:

答案 0 :(得分:2)

The actual specs are here,实际上并没有定义按键和输入的当前值的变化之间的关系。

无论他们读什么,(强调我的)

  

对于没有定义的输入激活行为但适用于这些事件的输入元素,只要用户在没有显式提交动作的情况下使用户的值发生更改,则用户代理must queue a task都会触发名为input的事件在输入元素上,并将bubbles属性初始化为true。如果控件失去焦点,则将触发相应的更改事件。

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

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

但是,当然,即使它没有违反任何规范,并且即使您有一个简单的修复程序(侦听输入事件),您可能仍要提交错误报告,至少是因为与其他供应商不同

答案 1 :(得分:-1)

我认为是因为Firefox正在处理setTimeout(fn,0)同步,这里也问过:Why does Firefox handle setTimeout(fn, 0) synchronous but setTimeout(fn, 1) asynchronous?

Chrome和节点将0替换为1:Difference between setTimeout(fn, 0) and setTimeout(fn, 1)? 因此,它们始终对他们不同步。 如果使用setTimeout(fn,1)运行它,它也可以在FF中使用。

如果要使其同步,请使用“ oninput”。 “ onkeydown”事件消失后,输入值不会完全更新。 在chrome / ff中使用超时或不超时

input.oninput = function() {
    this.value = this.value.toUpperCase()
};